<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="html">Martin Loitzl&apos;s Blog</title>
  <subtitle type="html">Thoughts and insights in my daily life as a software engineer.</subtitle>
  <id>https://blog.loitzl.com/</id>
  <link href="https://blog.loitzl.com/" rel="alternate" type="text/html"/>
  <link href="https://blog.loitzl.com/atom.xml" rel="self" type="application/atom+xml"/>
  <updated>2026-05-16T15:00:00.000Z</updated>
  <entry>
    <title type="html">Lose a Node, Keep the Service: Building a Zero-Downtime 3-Node k3s Cluster</title>
    <link href="https://blog.loitzl.com/posts/lose-a-node-keep-the-service-zero-downtime-k3s-cluster" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/lose-a-node-keep-the-service-zero-downtime-k3s-cluster</id>
    <updated>2026-05-16T15:00:00.000Z</updated>
    <summary type="html">How to build a 3-node k3s cluster where losing any single node — hardware failure, OS panic, accidental power cut — causes zero application downtime.</summary>
    <content type="html">&lt;p&gt;There’s a specific kind of peace that comes from watching a node go dark and seeing your application not even flinch.&lt;/p&gt;
&lt;p&gt;No alerts. No 500s. No panicked SSH sessions. Just a quiet log line somewhere saying a pod rescheduled, and life goes on.&lt;/p&gt;
&lt;p&gt;This post is about building exactly that: a 3-node &lt;a href=&quot;https://k3s.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;k3s&lt;/a&gt; cluster running &lt;a href=&quot;https://github.com/mloitzl/vinyl-vault&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;VinylVault&lt;/a&gt; — a full-stack app backed by a &lt;strong&gt;MongoDB replica set&lt;/strong&gt;, a &lt;strong&gt;Typesense Raft cluster&lt;/strong&gt;, and stateless Node.js services — where losing any single node is a non-event.&lt;/p&gt;
&lt;p&gt;The hardware is three Raspberry Pi 5s, each booting from a 1 TB M.2 NVMe SSD. The principles apply to any multi-node k3s setup.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-threat-model&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;the threat model&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#the-threat-model&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Threat Model&lt;/h2&gt;
&lt;p&gt;“High availability” gets thrown around loosely. Let’s be concrete. Our goal is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Losing any one of three nodes — permanently or temporarily — must not cause application downtime.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That means every layer of the stack needs to survive a 1-of-3 failure:&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Layer&lt;/th&gt;&lt;th&gt;Technology&lt;/th&gt;&lt;th&gt;Survival mechanism&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Control plane&lt;/td&gt;&lt;td&gt;k3s + embedded etcd&lt;/td&gt;&lt;td&gt;Raft quorum: 2/3 nodes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Storage&lt;/td&gt;&lt;td&gt;Longhorn&lt;/td&gt;&lt;td&gt;3-replica volumes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Search index&lt;/td&gt;&lt;td&gt;Typesense&lt;/td&gt;&lt;td&gt;Raft cluster: 3 nodes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Database&lt;/td&gt;&lt;td&gt;MongoDB&lt;/td&gt;&lt;td&gt;Replica set: 1 primary + 2 secondaries&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;App pods&lt;/td&gt;&lt;td&gt;Deployment + HPA&lt;/td&gt;&lt;td&gt;Topology spread: 1 pod per node&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Every layer uses the same fundamental idea: &lt;strong&gt;you need at least 2 surviving nodes to maintain quorum or keep a replica running&lt;/strong&gt;. With 3 total nodes, losing 1 always leaves 2. That’s your margin.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;layer-1-k3s-control-plane-with-etcd&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;layer 1 k3s control plane with etcd&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#layer-1-k3s-control-plane-with-etcd&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Layer 1: k3s Control Plane with etcd&lt;/h2&gt;
&lt;p&gt;k3s ships with embedded etcd. In a 3-node server setup, all three nodes form an etcd cluster. Etcd requires &lt;code&gt;⌊N/2⌋ + 1 = 2&lt;/code&gt; nodes for quorum, so losing 1 of 3 is fine.&lt;/p&gt;
&lt;p&gt;The critical detail is the &lt;strong&gt;stable control-plane endpoint&lt;/strong&gt;. If your API server address is a node IP and that node dies, &lt;code&gt;kubectl&lt;/code&gt; breaks and new pods can’t register. You need a VIP.&lt;/p&gt;
&lt;p&gt;We use &lt;a href=&quot;https://kube-vip.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;kube-vip&lt;/a&gt; in ARP mode. It runs as a DaemonSet on control-plane nodes and floats a virtual IP across whichever node is currently active:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# kube-vip manifest injected into /var/lib/rancher/k3s/server/manifests/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# VIP: 192.168.1.50 — DNS: cloudforge1-api → 192.168.1.50&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The k3s join command on all nodes always points at the VIP, never at a node IP:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;K3S_URL&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;https://cloudforge1-api:6443&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When a control-plane node fails, kube-vip re-elects and the VIP migrates. The API stays reachable. New pods can still be scheduled. The cluster continues.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;layer-2-distributed-storage-with-longhorn&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;layer 2 distributed storage with longhorn&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#layer-2-distributed-storage-with-longhorn&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Layer 2: Distributed Storage with Longhorn&lt;/h2&gt;
&lt;p&gt;Stateful services need persistent volumes. On a single node, a PVC is just a local directory. That’s fine until that node dies and the pod reschedules somewhere else — then the data is gone.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://longhorn.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Longhorn&lt;/a&gt; solves this by replicating volumes across nodes. With &lt;code&gt;defaultReplicaCount: 3&lt;/code&gt;, every PVC gets 3 replicas spread across your 3 nodes. The pod can reschedule to any surviving node and Longhorn will attach the volume there.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# gitops/clusters/homelab/platform/longhorn/helmrelease.yaml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;values&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  defaultSettings&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    defaultReplicaCount&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A subtle catch: &lt;strong&gt;&lt;code&gt;defaultReplicaCount&lt;/code&gt; only applies to new PVCs&lt;/strong&gt;. Existing volumes keep their original replica count. If you started on a single node and then scaled to 3, you need to patch old volumes manually:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;kubectl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; patch&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; volume&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;pvc-nam&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -n&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; longhorn-system&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  --type=merge&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -p&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &apos;{&quot;spec&quot;:{&quot;numberOfReplicas&quot;:3}}&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;layer-3-mongodb-replica-set&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;layer 3 mongodb replica set&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#layer-3-mongodb-replica-set&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Layer 3: MongoDB Replica Set&lt;/h2&gt;
&lt;p&gt;MongoDB’s replica set protocol is built for exactly this scenario. A 3-member set (1 primary, 2 secondaries) requires 2 nodes for election quorum. Lose 1 secondary: still have a primary. Lose the primary: the 2 remaining members elect a new one in seconds.&lt;/p&gt;
&lt;p&gt;The non-obvious part is &lt;strong&gt;how you configure the member hostnames&lt;/strong&gt;. This tripped us up.&lt;/p&gt;
&lt;p&gt;When MongoDB joins a replica set, it registers each member’s host address and uses it for inter-member replication. If you initialize the set pointing member 0 at a Kubernetes &lt;code&gt;ClusterIP&lt;/code&gt; service:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;rs&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;initiate&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;({ members: [{ _id: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, host: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;mongodb:27017&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; }] })&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…you’ve made a trap. The &lt;code&gt;mongodb&lt;/code&gt; ClusterIP will eventually load-balance across all 3 pods — including pods that are themselves in &lt;code&gt;STARTUP&lt;/code&gt; state. When a new secondary tries to sync, it picks the ClusterIP as its source and randomly hits a non-primary. Sync fails, pod crashes, crashes loop.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Always use StatefulSet headless DNS for RS members:&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;rs&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;initiate&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  _id: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;rs0&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  members: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    { _id: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, host: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;mongodb-0.mongodb-headless.vinylvault.svc.cluster.local:27017&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    { _id: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, host: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;mongodb-1.mongodb-headless.vinylvault.svc.cluster.local:27017&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    { _id: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, host: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;mongodb-2.mongodb-headless.vinylvault.svc.cluster.local:27017&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With headless DNS, each &lt;code&gt;mongodb-{N}&lt;/code&gt; name resolves directly to the pod’s IP. No load balancing. Replication always goes to the right pod.&lt;/p&gt;
&lt;p&gt;We wrap this in a Kubernetes &lt;code&gt;Job&lt;/code&gt; that runs on each fresh deploy. The init container waits until all 3 headless DNS names resolve before the main container runs &lt;code&gt;rs.initiate()&lt;/code&gt; — making the job idempotent and crash-safe:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# init container: wait for all 3 members to be reachable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; host&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mongodb-0.mongodb-headless&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mongodb-1.mongodb-headless&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mongodb-2.mongodb-headless&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  until&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; nc&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -z&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; ${&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;host&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;NAMESPACE&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;.svc.cluster.local&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 27017&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;do&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; sleep&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;done&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;layer-4-typesense-raft-cluster&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;layer 4 typesense raft cluster&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#layer-4-typesense-raft-cluster&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Layer 4: Typesense Raft Cluster&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://typesense.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Typesense&lt;/a&gt; uses Raft for its internal cluster consensus. Like etcd and MongoDB, a 3-node cluster tolerates 1 failure.&lt;/p&gt;
&lt;p&gt;The setup follows the same headless DNS pattern: each Typesense node needs to know the stable addresses of its peers at startup. We use an init container that resolves the headless DNS names and writes a &lt;code&gt;nodes&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;mongodb-0.typesense-headless.vinylvault.svc.cluster.local:8107:8108,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;mongodb-1.typesense-headless.vinylvault.svc.cluster.local:8107:8108,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;mongodb-2.typesense-headless.vinylvault.svc.cluster.local:8107:8108&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One thing that makes Typesense tricky in Kubernetes: pod IPs change on reschedule, but Typesense embeds peer addresses in its Raft log. To handle this gracefully, we run a &lt;strong&gt;&lt;code&gt;nodes-updater&lt;/code&gt; sidecar&lt;/strong&gt; that rewrites the nodes file every 20 seconds:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;nodes-updater&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  image&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;alpine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  command&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;/bin/sh&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;-c&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  args&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    - &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      while true; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        # resolve current IPs for all peers and rewrite /data/nodes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        sleep 20&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      done&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means Typesense always has fresh peer addresses without needing a full restart after a pod reschedule.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;layer-5-stateless-pods-the-topology-spread-trap&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;layer 5 stateless pods the topology spread trap&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#layer-5-stateless-pods-the-topology-spread-trap&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Layer 5: Stateless Pods — the Topology Spread Trap&lt;/h2&gt;
&lt;p&gt;MongoDB and Typesense handle their own resilience. Stateless pods (backend API, BFF, frontend) need a different approach: just make sure there’s always at least one replica on a surviving node.&lt;/p&gt;
&lt;p&gt;The naive solution — &lt;code&gt;replicas: 2&lt;/code&gt; — is not enough. Without placement constraints, Kubernetes might schedule both pods on the same node. Lose that node, lose both pods.&lt;/p&gt;
&lt;p&gt;The fix is &lt;code&gt;topologySpreadConstraints&lt;/code&gt; with &lt;code&gt;whenUnsatisfiable: DoNotSchedule&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;topologySpreadConstraints&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  - &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;maxSkew&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    topologyKey&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;kubernetes.io/hostname&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    whenUnsatisfiable&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;DoNotSchedule&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    labelSelector&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    matchLabelKeys&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      - &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;app&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;DoNotSchedule&lt;/code&gt; is the key word. &lt;code&gt;ScheduleAnyway&lt;/code&gt; (the default) is a hint — the scheduler &lt;em&gt;tries&lt;/em&gt; to spread, but will stack pods on one node if it’s under pressure. &lt;code&gt;DoNotSchedule&lt;/code&gt; is a hard rule: if spreading is impossible, the pod stays &lt;code&gt;Pending&lt;/code&gt;. That’s the guarantee we want.&lt;/p&gt;
&lt;p&gt;Pair this with &lt;code&gt;minReplicas: 2&lt;/code&gt; in the HPA:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# infra/k8s/overlays/homelab/kustomization.yaml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;target&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    kind&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;HorizontalPodAutoscaler&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  patch&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;-&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    - op: replace&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      path: /spec/minReplicas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      value: 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    - op: replace&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      path: /spec/maxReplicas&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      value: 3  # HPA can scale to fill all 3 nodes under load&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With 3 nodes and 2 replicas, the topology constraint places 1 pod on 2 different nodes. Lose either node: 1 replica survives, HPA immediately targets 2, a new pod schedules on the now-empty third node.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One gotcha with rolling updates:&lt;/strong&gt; during a rolling update, the scheduler sees terminating old pods as “still occupying” their node. New pods can temporarily stack on the same node before the old ones finish terminating. After every topology-changing deployment, a &lt;code&gt;kubectl rollout restart&lt;/code&gt; re-spreads the pods cleanly.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;what-surviving-node-loss-actually-looks-like&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;what surviving node loss actually looks like&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#what-surviving-node-loss-actually-looks-like&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What Surviving Node Loss Actually Looks Like&lt;/h2&gt;
&lt;p&gt;With all layers in place, this is what happens when a node goes down:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;etcd&lt;/strong&gt; detects the node is unreachable and marks it unhealthy. The remaining 2 nodes maintain quorum.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;kube-vip&lt;/strong&gt; (if the downed node held the VIP) re-elects and migrates the VIP to a healthy node within ~2 seconds. &lt;code&gt;kubectl&lt;/code&gt; keeps working.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Longhorn&lt;/strong&gt; rebuilds volume replicas on the surviving nodes. The volume remains accessible throughout.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MongoDB&lt;/strong&gt; — if the failed node held a secondary, the replica set continues with the surviving primary + secondary. If it held the primary, an election completes in 10–30 seconds, a new primary is elected, and writes resume.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Typesense&lt;/strong&gt; — same as MongoDB. 2/3 nodes maintain Raft quorum.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stateless pods&lt;/strong&gt; — the scheduler detects the node is &lt;code&gt;NotReady&lt;/code&gt;, evicts pods after &lt;code&gt;tolerationSeconds&lt;/code&gt; (default 300s for &lt;code&gt;node.kubernetes.io/not-ready&lt;/code&gt;). With topology spread, the surviving node already has a replica running and serving traffic throughout.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The only visible impact: if the pod on the downed node was handling an in-flight request, that request fails. The next request goes to the surviving replica. For most workloads, that’s not “downtime” — it’s a retry.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-numbers&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;the numbers&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#the-numbers&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Numbers&lt;/h2&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Scenario&lt;/th&gt;&lt;th&gt;MongoDB&lt;/th&gt;&lt;th&gt;Typesense&lt;/th&gt;&lt;th&gt;Stateless&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Node 1 down&lt;/td&gt;&lt;td&gt;RS: 1P + 1S ✅&lt;/td&gt;&lt;td&gt;Raft: 2/3 ✅&lt;/td&gt;&lt;td&gt;1 replica survives ✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Node 2 down&lt;/td&gt;&lt;td&gt;RS: 1P + 1S ✅&lt;/td&gt;&lt;td&gt;Raft: 2/3 ✅&lt;/td&gt;&lt;td&gt;1 replica survives ✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Node 3 down&lt;/td&gt;&lt;td&gt;RS: 1P + 1S ✅&lt;/td&gt;&lt;td&gt;Raft: 2/3 ✅&lt;/td&gt;&lt;td&gt;1 replica survives ✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2 nodes down&lt;/td&gt;&lt;td&gt;RS: no quorum ❌&lt;/td&gt;&lt;td&gt;Raft: no quorum ❌&lt;/td&gt;&lt;td&gt;0 replicas ❌&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;You can lose any one. You can’t lose two. That’s the deal with N=3.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;is-this-overkill-for-a-homelab&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;is this overkill for a homelab&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#is-this-overkill-for-a-homelab&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Is This Overkill for a Homelab?&lt;/h2&gt;
&lt;p&gt;Maybe. But “homelab” doesn’t mean “I don’t care about uptime.” It means I’m learning on my own hardware with my own time. And the thing I’ve learned most clearly from this project is that resilience doesn’t come from hope — it comes from explicit, testable configuration.&lt;/p&gt;
&lt;p&gt;Every piece of this setup is reproducible from a fresh flash of three 1 TB NVMe SSDs. Plug in a node, watch it join, watch Flux reconcile, watch the replica count go up. It’s infrastructure as a first-class concern.&lt;/p&gt;
&lt;p&gt;The Raspberry Pi 5s run k3s. The code runs in Git. The cluster runs itself.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;The full setup lives in &lt;a href=&quot;https://github.com/mloitzl/cloudforge&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;cloudforge&lt;/a&gt; (the GitOps infra repo) and &lt;a href=&quot;https://github.com/mloitzl/vinyl-vault&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;vinyl-vault&lt;/a&gt; (the app).&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;VinylVault is a personal record collection manager and architecture sandbox. Read more about the application layer in &lt;a href=&quot;/posts/implementing-hard-tenant-isolation-and-deterministic-data-at-scale/#page&quot;&gt;The Greenfield Sandbox&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">The Greenfield Sandbox: Implementing Hard Tenant Isolation and Deterministic Data at Scale</title>
    <link href="https://blog.loitzl.com/posts/implementing-hard-tenant-isolation-and-deterministic-data-at-scale" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/implementing-hard-tenant-isolation-and-deterministic-data-at-scale</id>
    <updated>2026-02-14T19:08:00.000Z</updated>
    <summary type="html">In over a decade of enterprise software development, I’ve noticed a recurring frustration: the more senior you become, the rarer it is to work on a truly &quot;greenfield&quot; project.</summary>
    <content type="html">&lt;p&gt;In over a decade of enterprise software development, I’ve noticed a recurring frustration: the more senior you become, the rarer it is to work on a truly “greenfield” project. Most of our day-to-day work involves navigating existing tech debt, respecting legacy migrations, or making incremental improvements to architectures decided years before we joined.&lt;/p&gt;
&lt;p&gt;It is notoriously difficult to test large-scale architectural ideas—like physical tenant isolation or the Backend-for-Frontend (BFF) pattern—within a established corporate codebase. The risk to production is too high, and the friction of legacy systems is too great.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/mloitzl/vinyl-vault/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;strong&gt;VinylVault&lt;/strong&gt;&lt;/a&gt; is my response to that constraint. It started as a personal record collection manager, but quickly evolved into a laboratory where I could implement a high-scale SaaS architecture from the ground up, focusing on three enterprise-level pillars: &lt;strong&gt;Hard Data Isolation&lt;/strong&gt;, &lt;strong&gt;Security by Design&lt;/strong&gt;, and &lt;strong&gt;Deterministic Metadata Aggregation&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;1-physical-isolation-why-tenantid-isnt-enough&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;1 physical isolation why tenantid isnt enough&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#1-physical-isolation-why-tenantid-isnt-enough&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. Physical Isolation: Why &lt;code&gt;tenant_id&lt;/code&gt; Isn’t Enough&lt;/h2&gt;
&lt;p&gt;In the enterprise world, “Multi-Tenancy” is often handled logically via a column in a shared table. While this works, it creates a massive “leaky abstraction” risk and makes heavy users (the “noisy neighbor” problem) hard to manage.&lt;/p&gt;
&lt;p&gt;For VinylVault, I implemented &lt;strong&gt;Physical Tenant Isolation&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;dynamic-database-routing&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;dynamic database routing&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#dynamic-database-routing&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Dynamic Database Routing&lt;/h3&gt;
&lt;p&gt;Every user or organization gets their own dedicated MongoDB database (e.g., &lt;code&gt;vinylvault_user_123&lt;/code&gt;). My Domain Backend acts as a dynamic router. When a request hits the API, the &lt;code&gt;getTenantDb&lt;/code&gt; connection manager performs a just-in-time lookup:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It verifies the &lt;code&gt;tenantId&lt;/code&gt; from a claims-based JWT.&lt;/li&gt;
&lt;li&gt;It checks an internal connection pool (a &lt;code&gt;Map&amp;#x3C;string, Db&gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;If a connection is stale or missing, it dynamically connects to the tenant’s specific sandbox.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This ensures that a coding error in a resolver can &lt;strong&gt;never&lt;/strong&gt; result in data leakage between users—the database connection itself simply doesn’t have access to other tenants’ data.&lt;/p&gt;
&lt;h3 id=&quot;the-indexing-challenge&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;the indexing challenge&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#the-indexing-challenge&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Indexing Challenge&lt;/h3&gt;
&lt;p&gt;Managing hundreds of databases means you can’t manually manage indexes. I built an &lt;strong&gt;Asynchronous Reconciliation Layer&lt;/strong&gt;. The first time a tenant accesses the system, the backend automatically verifies and creates the necessary text indexes and atomic counter documents before resolving the first GraphQL query.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;2-the-blended-scoring-engine-achieving-determinism&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;2 the blended scoring engine achieving determinism&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#2-the-blended-scoring-engine-achieving-determinism&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. The Blended Scoring Engine: Achieving Determinism&lt;/h2&gt;
&lt;p&gt;One of the hardest problems in music data is the inconsistency of community-driven APIs like Discogs and MusicBrainz. If you scan a barcode and get three results for “Nirvana - Nevermind,” how do you programmatically select the “correct” one?&lt;/p&gt;
&lt;p&gt;I built a &lt;strong&gt;Normalization and Weighted Scoring Pipeline&lt;/strong&gt; that treats these external APIs as raw, untrusted data.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Heuristic Grouping:&lt;/strong&gt; I use configurable affixes to strip non-semantic noise like &lt;code&gt;(2022 Remaster)&lt;/code&gt; or &lt;code&gt;[Bonus Tracks]&lt;/code&gt;, allowing me to group disparate results into a single deterministic &lt;code&gt;groupingKey&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Weighted Scoring:&lt;/strong&gt; Every release is scored based on metadata completeness (tracklists, label info, high-res cover art). Vinyl formats receive a specific weight boost.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Double Dagger Delimiters:&lt;/strong&gt; To manage composite IDs across different sources, I used the &lt;code&gt;‡&lt;/code&gt; (double dagger) character (e.g., &lt;code&gt;SOURCE‡ID&lt;/code&gt;). This avoids the collision issues common with colons or dashes found in external IDs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This ensures &lt;strong&gt;Traceability&lt;/strong&gt;. My API doesn’t just return a result; it returns the “why” behind the choice, exposing the score breakdown for every candidate.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;3-the-bff-pattern-security-by-design&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;3 the bff pattern security by design&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#3-the-bff-pattern-security-by-design&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;3. The BFF Pattern: Security by Design&lt;/h2&gt;
&lt;p&gt;Security in modern web apps is often compromised by storing sensitive JWTs in &lt;code&gt;localStorage&lt;/code&gt;. To solve this, I implemented a &lt;strong&gt;Backend-for-Frontend (BFF)&lt;/strong&gt; layer.&lt;/p&gt;
&lt;h3 id=&quot;jwt-hiding&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;jwt hiding&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#jwt-hiding&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;JWT Hiding&lt;/h3&gt;
&lt;p&gt;The BFF handles the “dirty work” of identity. The frontend only ever deals with a &lt;strong&gt;secure, HTTP-only session cookie&lt;/strong&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The BFF validates the session.&lt;/li&gt;
&lt;li&gt;It identifies the user’s active tenant.&lt;/li&gt;
&lt;li&gt;It generates a &lt;strong&gt;short-lived, internally-scoped JWT&lt;/strong&gt; to talk to the Domain Backend.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This pattern, known as &lt;strong&gt;“Token Exchange,”&lt;/strong&gt; means the frontend never sees the primary auth tokens, significantly reducing the surface area for XSS attacks.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;4-scaling-the-frontend-strict-relay-atomic-design&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;4 scaling the frontend strict relay atomic design&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#4-scaling-the-frontend-strict-relay-atomic-design&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;4. Scaling the Frontend: Strict Relay &amp;#x26; Atomic Design&lt;/h2&gt;
&lt;p&gt;After a decade of watching Redux stores grow into unmaintainable monsters, I refactored the VinylVault frontend to use &lt;strong&gt;Relay&lt;/strong&gt; and a custom &lt;strong&gt;Atomic Design System&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;fragment-colocation&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;fragment colocation&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#fragment-colocation&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Fragment Colocation&lt;/h3&gt;
&lt;p&gt;Relay is my choice for enterprise scale because it forces &lt;strong&gt;Strict Fragment Colocation&lt;/strong&gt;. Every component (like &lt;code&gt;RecordCard&lt;/code&gt;) defines exactly what data it needs via a GraphQL fragment. This creates a “Contract-First” UI where over-fetching is physically impossible.&lt;/p&gt;
&lt;h3 id=&quot;render-as-you-fetch&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;render as you fetch&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#render-as-you-fetch&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;“Render-as-you-Fetch”&lt;/h3&gt;
&lt;p&gt;I implemented the &lt;code&gt;useQueryLoader&lt;/code&gt; pattern. In the collection view, the data fetch begins the millisecond a user initiates a navigation event. By the time the component finishes its first render, the data is already arriving from the BFF.&lt;/p&gt;
&lt;h3 id=&quot;the-silent-tenant-switch-bug&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;the silent tenant switch bug&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#the-silent-tenant-switch-bug&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The “Silent” Tenant-Switch Bug&lt;/h3&gt;
&lt;p&gt;In a multi-database architecture, the frontend cache is a liability. If you switch from your Personal collection to an Org collection, Relay’s normalized store might still hold IDs from the previous tenant.&lt;/p&gt;
&lt;p&gt;To fix this, I implemented a &lt;strong&gt;Manual Store Purge&lt;/strong&gt; during the tenant switch mutation:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; switchTenant&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; useCallback&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (tenantId&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;  // 1. BFF updaes the session and returns new context&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; data&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; executeGraphQLMutation&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;query&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, { &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;tenantId&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;  // 2. CRITICAL: Wipe the Relay cache to prevent ID overlap between DBs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  RelayEnvironment&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;getStore&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;getSource&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;clear&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;  // 3. Update React context and navigate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  setActiveTenant&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;activeTenant&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  navigate&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;); &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}, []);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-lessons-learned&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;the lessons learned&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#the-lessons-learned&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Lessons Learned&lt;/h2&gt;
&lt;p&gt;Building VinylVault on my own terms allowed me to prove that “Enterprise Grade” doesn’t have to mean “Slow and Heavy.” By using a &lt;strong&gt;Monorepo (pnpm workspaces)&lt;/strong&gt;, &lt;strong&gt;Stateless Backend Routing&lt;/strong&gt;, and &lt;strong&gt;Strict GraphQL Contracts&lt;/strong&gt;, I’ve built a system that is arguably more robust than many of the production environments I’ve inherited in the past.&lt;/p&gt;
&lt;p&gt;It turns out that when you remove the constraints of legacy systems, you can build software that is not only scalable and secure but a joy to maintain.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Star it on GitHub: &lt;a href=&quot;https://github.com/mloitzl/vinyl-vault/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Vinyl Vault&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Live Demo @ &lt;a href=&quot;https://vinyl-vault-demo.loitzl.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Vinyl Vault - Demo&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-stack-summary&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;the stack summary&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#the-stack-summary&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Stack Summary:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Architecture:&lt;/strong&gt; 3-Tier (Frontend -&gt; BFF -&gt; Domain Backend)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Isolation:&lt;/strong&gt; Database-per-tenant (MongoDB)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fetching:&lt;/strong&gt; Relay (Strict Fragment Colocation)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Language:&lt;/strong&gt; TypeScript (Strict Mode)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Branding:&lt;/strong&gt; Tailwind CSS with a custom Atomic UI Library&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;</content>
  </entry>
  <entry>
    <title type="html">Variance and covariance explained with C#</title>
    <link href="https://blog.loitzl.com/posts/variance-and-covariance-explained-with-csharp" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/variance-and-covariance-explained-with-csharp</id>
    <updated>2025-08-25T19:08:00.000Z</updated>
    <summary type="html">A deep dive into variance and covariance with modern C# examples. Featuring Orwell’s Animal Farm, dependency injection scenarios, and a short detour into TypeScript.</summary>
    <content type="html">&lt;p&gt;The other day a colleague asked me about the difference between variance and covariance in C#.
I smiled, and realized I probably owed him an article.&lt;/p&gt;
&lt;p&gt;Variance in programming has a reputation for being boring theory reserved for academic types and Stack Overflow answers from 2011. But it is &lt;em&gt;not&lt;/em&gt;. It’s one of those topics that silently runs the type system you rely on every day. And once you grasp it, you’ll spot opportunities to write cleaner, more composable code.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-gentle-theory-bit&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;the gentle theory bit&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#the-gentle-theory-bit&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Gentle Theory Bit&lt;/h2&gt;
&lt;p&gt;Let’s start with crisp definitions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Variance&lt;/strong&gt; describes how subtype relationships behave when a type parameter is involved.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Covariance&lt;/strong&gt; means “I can go upwards in the inheritance tree safely.” If &lt;code&gt;Pig&lt;/code&gt; inherits &lt;code&gt;Animal&lt;/code&gt;, then &lt;code&gt;IEnumerable&amp;#x3C;Pig&gt;&lt;/code&gt; can be treated as &lt;code&gt;IEnumerable&amp;#x3C;Animal&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contravariance&lt;/strong&gt; means the opposite direction. It allows safe handling of more general inputs: if &lt;code&gt;Pig&lt;/code&gt; is an &lt;code&gt;Animal&lt;/code&gt;, then &lt;code&gt;IComparer&amp;#x3C;Animal&gt;&lt;/code&gt; can also be an &lt;code&gt;IComparer&amp;#x3C;Pig&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Or, put differently:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;out&lt;/code&gt; = covariance (outputs)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;in&lt;/code&gt; = contravariance (inputs)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here’s a neat mnemonic: the &lt;code&gt;N&lt;/code&gt; in &lt;code&gt;in&lt;/code&gt; belongs to Co&lt;strong&gt;N&lt;/strong&gt;travariance. The &lt;code&gt;out&lt;/code&gt; keyword simply points to co&lt;strong&gt;V&lt;/strong&gt;ariance, as it describes output positions.&lt;/p&gt;
&lt;p&gt;Two classic examples from .NET’s BCL should be familiar:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; interface&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; IEnumerable&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;out&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; interface&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; IComparer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; { ... }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Why these choices?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;IEnumerable&amp;#x3C;T&gt;&lt;/code&gt; produces sequence elements, so it’s &lt;strong&gt;covariant&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IComparer&amp;#x3C;T&gt;&lt;/code&gt; consumes elements to compare them, so it’s &lt;strong&gt;contravariant&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;our-animal-hierarchy&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;our animal hierarchy&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#our-animal-hierarchy&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Our Animal Hierarchy&lt;/h2&gt;
&lt;p&gt;First, the characters:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; abstract&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; Animal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; Name { &lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    protected&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; name) &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Name&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; name&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; abstract&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Speak&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; Pig&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Pig&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; name) : &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;base&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) { }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; override&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Speak&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;        Console&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;$&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;: Oink!&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; Horse&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Horse&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; name) : &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;base&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) { }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; override&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Speak&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;        Console&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;$&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;: Neigh!&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; napoleon &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; Pig&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;Napoleon&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; boxer &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; Horse&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;Boxer&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2 id=&quot;covariance-with-out&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;covariance with out&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#covariance-with-out&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Covariance With &lt;code&gt;out&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Covariance shines when you &lt;em&gt;produce&lt;/em&gt; (return) something. The classic example:&lt;br&gt;
&lt;code&gt;IEnumerable&amp;#x3C;out T&gt;&lt;/code&gt; is covariant. This means you can assign a collection of derived types to a collection of base types:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IEnumerable&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Pig&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; pigs &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Pig&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; { &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;napoleon&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IEnumerable&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; animals &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; pigs&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// Works thanks to covariance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;foreach&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; animal &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; animals&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Speak&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here the variance lets us &lt;em&gt;consume&lt;/em&gt; the sequence as its base type. &lt;code&gt;Napoleon&lt;/code&gt; still squeals as expected.&lt;/p&gt;
&lt;h3 id=&quot;async-streams-iasyncenumerableout-t&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;async streams iasyncenumerableout t&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#async-streams-iasyncenumerableout-t&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Async Streams (&lt;code&gt;IAsyncEnumerable&amp;#x3C;out T&gt;&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;With async streams introduced in C# 8, the variance principle shines:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; IAsyncEnumerable&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Dog&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;GetDogsAsync&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;() { &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;. }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// Covariance lets you assign to a more general type:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IAsyncEnumerable&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; animals &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; GetDogsAsync&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Without covariance, this neat and type-safe upcasting wouldn’t be allowed.&lt;/p&gt;
&lt;h3 id=&quot;read-only-collections&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;read only collections&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#read-only-collections&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Read-Only Collections&lt;/h3&gt;
&lt;p&gt;Read-only interfaces are typically covariant since they only expose data:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IReadOnlyList&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Dog&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; dogs &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; ..&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;IReadOnlyList&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; animals&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; dogs&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// perfectly valid due to covariance&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;IReadOnlyList&amp;#x3C;out T&gt;&lt;/code&gt; can produce values but not consume them, so safe covariance applies.&lt;/p&gt;
&lt;p&gt;Contrast with mutable collections:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IList&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; animals &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Dog&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;(); &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// Error: IList&amp;#x3C;T&gt; is invariant&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;animals&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Add&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; Cat&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;());                  &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// This would break type safety, so disallowed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;async-linq-extensions&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;async linq extensions&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#async-linq-extensions&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Async LINQ Extensions&lt;/h3&gt;
&lt;p&gt;Async LINQ operators use variance too:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;await&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; foreach&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; a &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; GetDogsAsync&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;OfType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;    ..&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, covariance in &lt;code&gt;IAsyncEnumerable&amp;#x3C;out T&gt;&lt;/code&gt; allows seamless upcasting during enumeration.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;contravariance-with-in&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;contravariance with in&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#contravariance-with-in&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Contravariance With &lt;code&gt;in&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Contravariance is the mirror world. It occurs where a type parameter only appears as an input.&lt;br&gt;
Imagine we have a farm-wide announcer whose sole job is to talk to animals:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; interface&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; IAnnouncer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;    void&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Announce&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; animal);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; LoudAnnouncer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IAnnouncer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Announce&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; animal)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;    =&gt;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Console&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;WriteLine&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;$&quot;Announcing: &lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; is here!&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, thanks to contravariance, we can reuse &lt;code&gt;IAnnouncer&amp;#x3C;Animal&gt;&lt;/code&gt; even if the code expects a &lt;code&gt;IAnnouncer&amp;#x3C;Pig&gt;&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IAnnouncer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Pig&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; pigAnnouncer &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; LoudAnnouncer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;pigAnnouncer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Announce&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;napoleon&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;in&lt;/code&gt; keyword makes this possible: an announcer that works for “all animals” can also be used where “only pigs” are requested.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;dependency-injection-and-contravariance&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;dependency injection and contravariance&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#dependency-injection-and-contravariance&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Dependency Injection And Contravariance&lt;/h2&gt;
&lt;p&gt;Variance becomes especially powerful when combined with dependency injection (DI).&lt;/p&gt;
&lt;p&gt;Imagine you have a service that requires an announcer &lt;em&gt;just&lt;/em&gt; for pigs:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; PigShow&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    private&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; IAnnouncer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Pig&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; _announcer;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; PigShow&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IAnnouncer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Pig&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; announcer) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;        _announcer&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; announcer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Run&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Pig&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; pig) &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;        _announcer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Announce&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;pig&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You don’t want to write multiple announcers for every animal type. Instead, you register a single &lt;code&gt;IAnnouncer&amp;#x3C;Animal&gt;&lt;/code&gt; in DI:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;services&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AddSingleton&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IAnnouncer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;LoudAnnouncer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;services&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AddTransient&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;PigShow&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now DI happily resolves &lt;code&gt;IAnnouncer&amp;#x3C;Pig&gt;&lt;/code&gt; requests using the &lt;code&gt;IAnnouncer&amp;#x3C;Animal&gt;&lt;/code&gt; implementation, because contravariance made that conversion legal.&lt;/p&gt;
&lt;p&gt;This is both elegant and practical: a single implementation scales across multiple injected scenarios.&lt;/p&gt;
&lt;h3 id=&quot;comparers-and-dependency-injection&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;comparers and dependency injection&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#comparers-and-dependency-injection&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Comparers and Dependency Injection&lt;/h3&gt;
&lt;p&gt;Contravariance comes in handy when you consume values, for example with comparers:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; AnimalNameComparer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IComparer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Compare&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;? x, &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;? y) &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;        string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Compare&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Name&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;StringComparison&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Ordinal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IComparer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Dog&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; dogComparer &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; AnimalNameComparer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This compiles because &lt;code&gt;IComparer&amp;#x3C;T&gt;&lt;/code&gt; is contravariant (&lt;code&gt;in T&lt;/code&gt;): a comparer for &lt;code&gt;Animal&lt;/code&gt; can also handle &lt;code&gt;Dog&lt;/code&gt;. Handy for registering services in dependency injection containers for base types while resolving derived types.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-classic-pitfalls&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;the classic pitfalls&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#the-classic-pitfalls&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Classic Pitfalls&lt;/h2&gt;
&lt;p&gt;Variance doesn’t come for free:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Covariance (&lt;code&gt;out&lt;/code&gt;) applies only when you &lt;em&gt;return&lt;/em&gt; data, never when you need to &lt;em&gt;put&lt;/em&gt; something inside.&lt;/li&gt;
&lt;li&gt;Contravariance (&lt;code&gt;in&lt;/code&gt;) works when consuming inputs, not producing outputs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;why-isnt-everything-covariant-or-contravariant&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;why isnt everything covariant or contravariant&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#why-isnt-everything-covariant-or-contravariant&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Why isn’t Everything Covariant or Contravariant?&lt;/h3&gt;
&lt;p&gt;Variance is only safe if the interface respects its output/input constraints. If an interface both consumes and produces &lt;code&gt;T&lt;/code&gt;, the compiler forbids variance to prevent runtime type errors.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IList&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; animals &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Dog&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;(); &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// Compilation error&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Allowing variance here would mean you could insert a &lt;code&gt;Cat&lt;/code&gt; into a list of &lt;code&gt;Dog&lt;/code&gt;, breaking runtime safety.&lt;/p&gt;
&lt;h3 id=&quot;arrays-are-covariant&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;arrays are covariant&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#arrays-are-covariant&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Arrays are covariant&lt;/h3&gt;
&lt;p&gt;C# allows this:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[] strings &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[] { &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[] objects &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; strings&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// ✅ Allowed, because arrays are covariant&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So an array of string can be treated as an array of object.
That’s covariance: string → object (derived → base).&lt;/p&gt;
&lt;p&gt;Why is this unsafe?&lt;/p&gt;
&lt;p&gt;At runtime you can now do:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[] objects &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;objects&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;hello&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;   &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// fine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;objects&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 42&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;        &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// ❌ runtime error!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At compile time, the compiler thinks this is fine (42 is an object).
But at runtime, the actual array is a string[], and 42 is not a string.
So the runtime throws an ArrayTypeMismatchException.
👉 This means covariance of arrays breaks type safety.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;variance-in-javascript-and-typescript&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;variance in javascript and typescript&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#variance-in-javascript-and-typescript&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Variance In JavaScript And TypeScript&lt;/h2&gt;
&lt;p&gt;In JavaScript, you don’t have variance. Everything is duck typing and vibes.&lt;br&gt;
But in TypeScript, variance sneaks in through assignability rules:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;typescript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; Announcer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    announce&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(animal&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; pigAnnouncer&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; Announcer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Pig&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; animalAnnouncer&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; Announcer&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Animal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By default, TypeScript treats function parameters as &lt;em&gt;bivariant&lt;/em&gt; (both co- and contravariant-ish), which is convenient but not always type-safe.&lt;br&gt;
Strict mode (&lt;code&gt;strictFunctionTypes&lt;/code&gt;) nudges it closer to C#’s model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Return types are &lt;strong&gt;covariant&lt;/strong&gt; – it’s safe for a &lt;code&gt;Pig&lt;/code&gt; to be returned where &lt;code&gt;Animal&lt;/code&gt; is expected.&lt;/li&gt;
&lt;li&gt;Parameter types are &lt;strong&gt;contravariant&lt;/strong&gt; – you can provide an &lt;code&gt;Announcer&amp;#x3C;Animal&gt;&lt;/code&gt; if someone asks for an &lt;code&gt;Announcer&amp;#x3C;Pig&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So the concepts map over neatly, but TypeScript hides most of the painful corners for you. Meanwhile, C# makes you explicitly sprinkle &lt;code&gt;in&lt;/code&gt; and &lt;code&gt;out&lt;/code&gt; keywords like salt on your generics.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;conclusion&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;conclusion&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#conclusion&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Variance is one of those “once seen, can’t be unseen” aspects of type systems.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Covariance (&lt;code&gt;out&lt;/code&gt;)&lt;/strong&gt; lets you use derived collections as base collections.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contravariance (&lt;code&gt;in&lt;/code&gt;)&lt;/strong&gt; lets you use general consumers in more specific contexts.&lt;/li&gt;
&lt;li&gt;Dependency injection frameworks love contravariance.&lt;/li&gt;
&lt;li&gt;Even JavaScript/TypeScript play in this space, albeit more loosely.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And in case you forget: just remember the &lt;code&gt;N&lt;/code&gt; in &lt;code&gt;in&lt;/code&gt; belongs to Co&lt;strong&gt;N&lt;/strong&gt;travariance.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">Deleting deleted group connected SharePoint Online Sites</title>
    <link href="https://blog.loitzl.com/posts/deleting-deleted-sharepointonline-sites" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/deleting-deleted-sharepointonline-sites</id>
    <updated>2025-04-10T11:11:11.000Z</updated>
    <summary type="html">When a SharePoint Online Site gets deleted, it might have been connected to a M365 group. This article explains how to remove the site from deleted sites.</summary>
    <content type="html">&lt;p&gt;When a SharePoint Online site was deleted, it might have been connected to a M365 group. In this case it cannot be removed from deleted sites.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/deleting-group-connected-sites-6d80a338/320.webp 320w, /generated/deleting-group-connected-sites-6d80a338/480.webp 480w, /generated/deleting-group-connected-sites-6d80a338/640.webp 640w, /generated/deleting-group-connected-sites-6d80a338/750.webp 750w, /generated/deleting-group-connected-sites-6d80a338/778.webp 778w&quot; sizes=&quot;(min-width: 778px) 778px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Permanently Delete greyed out&quot; src=&quot;/generated/deleting-group-connected-sites-6d80a338/778.png&quot; srcset=&quot;/generated/deleting-group-connected-sites-6d80a338/320.png 320w, /generated/deleting-group-connected-sites-6d80a338/480.png 480w, /generated/deleting-group-connected-sites-6d80a338/640.png 640w, /generated/deleting-group-connected-sites-6d80a338/750.png 750w, /generated/deleting-group-connected-sites-6d80a338/778.png 778w&quot; sizes=&quot;(min-width: 778px) 778px, 100vw&quot; width=&quot;778&quot; height=&quot;317&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;First delete the group from Entra (Azure AD)&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/delete-entra-group-6d80a338/320.webp 320w, /generated/delete-entra-group-6d80a338/480.webp 480w, /generated/delete-entra-group-6d80a338/640.webp 640w, /generated/delete-entra-group-6d80a338/750.webp 750w, /generated/delete-entra-group-6d80a338/828.webp 828w, /generated/delete-entra-group-6d80a338/865.webp 865w&quot; sizes=&quot;(min-width: 865px) 865px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;remove M365 group in entra&quot; src=&quot;/generated/delete-entra-group-6d80a338/865.png&quot; srcset=&quot;/generated/delete-entra-group-6d80a338/320.png 320w, /generated/delete-entra-group-6d80a338/480.png 480w, /generated/delete-entra-group-6d80a338/640.png 640w, /generated/delete-entra-group-6d80a338/750.png 750w, /generated/delete-entra-group-6d80a338/828.png 828w, /generated/delete-entra-group-6d80a338/865.png 865w&quot; sizes=&quot;(min-width: 865px) 865px, 100vw&quot; width=&quot;865&quot; height=&quot;510&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Using PnP Powershell command &lt;code&gt;Get-PnPDeletedMicrosoft365Group&lt;/code&gt; it is possible to find the deleted M365 Group, and remove it with &lt;code&gt;Remove-PnPDeletedMicrosoft365Group&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;PS &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Users&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;martin&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Get-PnPDeletedMicrosoft365Group&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;DisplayName                               Id                                   HasTeam SiteUrl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;-----------&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;                               --&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;                                   -------&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -------&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;PnP Microsoft &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;365&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; library test with group e351a3ff&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1595&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;4979&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;b588&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;88038f993cc6 False&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Remove-PnPDeletedMicrosoft365Group&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Identity e351a3ff&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1595&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;4979&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;b588&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;88038f993cc6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Afterwards the  permanetly delete button works:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/deleting-group-connected-sites-works-6d80a338/320.webp 320w, /generated/deleting-group-connected-sites-works-6d80a338/480.webp 480w, /generated/deleting-group-connected-sites-works-6d80a338/640.webp 640w, /generated/deleting-group-connected-sites-works-6d80a338/750.webp 750w, /generated/deleting-group-connected-sites-works-6d80a338/793.webp 793w&quot; sizes=&quot;(min-width: 793px) 793px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Permanently Delete greyed out&quot; src=&quot;/generated/deleting-group-connected-sites-works-6d80a338/793.png&quot; srcset=&quot;/generated/deleting-group-connected-sites-works-6d80a338/320.png 320w, /generated/deleting-group-connected-sites-works-6d80a338/480.png 480w, /generated/deleting-group-connected-sites-works-6d80a338/640.png 640w, /generated/deleting-group-connected-sites-works-6d80a338/750.png 750w, /generated/deleting-group-connected-sites-works-6d80a338/793.png 793w&quot; sizes=&quot;(min-width: 793px) 793px, 100vw&quot; width=&quot;793&quot; height=&quot;329&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Bonus Feature: Since we are already connected, we can also use &lt;code&gt;Get-PnPTenantDeletedSite&lt;/code&gt; and &lt;code&gt;Remove-PnPTenantDeletedSite&lt;/code&gt; to remove the site permanently.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;PS &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Users&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;martin&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Get-PnPTenantDeletedSite&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;SiteId                 : b0d12530&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;9a8d&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;4173&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;874b&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;eb8001090fdf&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Url                    : https:&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;loitzl2.sharepoint.com&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;sites&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;pnpcoresdktestgroup2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Status                 : Recycled&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;DeletionTime           : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;10.04&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;2025&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 18&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;37&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;19&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;DaysRemaining          : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;92&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;StorageQuota           : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;26214400&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ResourceQuota          : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;300&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;PS &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Users&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;martin&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Remove-PnPTenantDeletedSite&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Force https:&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;loitzl2.sharepoint.com&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;sites&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;pnpcoresdktestgroup&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
  </entry>
  <entry>
    <title type="html">Getting an App Only access token for SharePoint REST APIs</title>
    <link href="https://blog.loitzl.com/posts/getting-an-app-only-access-token-for-sharepoint-rest-apis" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/getting-an-app-only-access-token-for-sharepoint-rest-apis</id>
    <updated>2023-03-13T11:11:11.000Z</updated>
    <summary type="html">The SharePoint API only accepts access (bearer) tokens that have been acquired using client assertions. This article explains how to do that on protcol level.</summary>
    <content type="html">&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/pexels-pavel-danilyuk-8438966-da8f3a3c/320.webp 320w, /generated/pexels-pavel-danilyuk-8438966-da8f3a3c/480.webp 480w, /generated/pexels-pavel-danilyuk-8438966-da8f3a3c/640.webp 640w, /generated/pexels-pavel-danilyuk-8438966-da8f3a3c/750.webp 750w, /generated/pexels-pavel-danilyuk-8438966-da8f3a3c/828.webp 828w, /generated/pexels-pavel-danilyuk-8438966-da8f3a3c/960.webp 960w, /generated/pexels-pavel-danilyuk-8438966-da8f3a3c/1279.webp 1279w&quot; sizes=&quot;(min-width: 1279px) 1279px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Photo by Pavel Danilyuk: https://www.pexels.com/photo/robot-holding-a-red-flower-8438966/&quot; src=&quot;/generated/pexels-pavel-danilyuk-8438966-da8f3a3c/1279.jpeg&quot; srcset=&quot;/generated/pexels-pavel-danilyuk-8438966-da8f3a3c/320.jpeg 320w, /generated/pexels-pavel-danilyuk-8438966-da8f3a3c/480.jpeg 480w, /generated/pexels-pavel-danilyuk-8438966-da8f3a3c/640.jpeg 640w, /generated/pexels-pavel-danilyuk-8438966-da8f3a3c/750.jpeg 750w, /generated/pexels-pavel-danilyuk-8438966-da8f3a3c/828.jpeg 828w, /generated/pexels-pavel-danilyuk-8438966-da8f3a3c/960.jpeg 960w, /generated/pexels-pavel-danilyuk-8438966-da8f3a3c/1279.jpeg 1279w&quot; sizes=&quot;(min-width: 1279px) 1279px, 100vw&quot; width=&quot;1279&quot; height=&quot;854&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h1 id=&quot;objectives&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;objectives&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#objectives&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Objectives&lt;/h1&gt;
&lt;p&gt;Recently I was asked to access SharePoint Online APIs using App Only access.
I always used libraries (like MSAL, or PnP Core) for that and they always use signed client assertions for acquiring bearer tokens.&lt;/p&gt;
&lt;p&gt;This time I needed some deeper insights and analyzed the whole process on protocol level.&lt;/p&gt;
&lt;h1 id=&quot;app-registration&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;app registration&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#app-registration&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;App Registration&lt;/h1&gt;
&lt;p&gt;As a pre-requisite we need an Azure Active Directory App registration with access to SharePoint. There are plenty of guides on the net for that, for example &lt;a href=&quot;/posts/creating-sharePoint-managed-metadata-terms-using-the-new-pnp-core-sdk/#setup-authentication&quot;&gt;Setup Authentication&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In short, I used &lt;code&gt;openssl&lt;/code&gt; to create self-signed certificates…&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# Create the certificate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; openssl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; req&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -x509&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -newkey&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; rsa:4096&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -keyout&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; key.pem&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -out&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; cert.pem&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -days&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 365&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# Convert to pfx file&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; openssl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; pkcs12&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -export&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -out&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; certificate.pfx&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -inkey&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; key.pem&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -in&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; cert.pem&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…and the &lt;a href=&quot;https://pnp.github.io/powershell/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PnP PowerShell&lt;/a&gt; cmdlet &lt;a href=&quot;https://pnp.github.io/powershell/cmdlets/Register-PnPAzureADApp.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Register-PnPAzureADApp&lt;/a&gt; to create the Azure AD app registration.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Register-PnPAzureADApp&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ApplicationName TestApp1 &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Tenant &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;tenant&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;onmicrosoft.com&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;CertificatePath certificate.pfx &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;CertificatePassword (&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;ConvertTo-SecureString&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;String &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;&amp;#x3C;cert password&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;AsPlainText &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Force) &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Username &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;&amp;#x3C;user&gt;@&amp;#x3C;tenant&gt;.onmicrosoft.com&quot;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Password (&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;ConvertTo-SecureString&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;String &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;&amp;#x3C;password&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;AsPlainText &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Force) &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;SharePointApplicationPermissions Sites.Read.All&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;getting-an-oauth2-token-using-a-client-assertion&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;getting an oauth2 token using a client assertion&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#getting-an-oauth2-token-using-a-client-assertion&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Getting an OAuth2 Token using a Client Assertion&lt;/h1&gt;
&lt;p&gt;The Request for getting the app only access token looks like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;http&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;POST&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; https://login.microsoftonline.com/&amp;#x3C;tenant-id&gt;/oauth2/v2.0/token&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Content-Type&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; application/x-www-form-urlencoded&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;client_id=&amp;#x3C;client-id&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;grant_type&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;client_credentials&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;scope&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;https://&amp;#x3C;tenant&gt;.sharepoint.com/.default&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;client_assertion&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&amp;#x3C;signed jwt client assertion&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;client_assertion_type&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;urn:ietf:params:oauth:client-assertion-type:jwt-bearer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;tenant-id&lt;/code&gt; is the id of the Azure AD tenant, &lt;code&gt;client-id&lt;/code&gt; the app id of the Azure AD App registration. The grant type is set to &lt;code&gt;client_credentials&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The scope needs to be set to the SharePoint URL, followed by &lt;code&gt;.default&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The client assertion type is set to &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc7523#section-8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;jwt-bearer&lt;/code&gt;&lt;/a&gt;, and the client assertion itself a base64 jwt similar to…&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  &quot;iat&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1678548857&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  &quot;exp&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1678552457&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  &quot;iss&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;791ff0ac-1f93-47fc-8629-6b20f360036f&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  &quot;sub&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;791ff0ac-1f93-47fc-8629-6b20f360036f&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  &quot;aud&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;https://login.microsoftonline.com/0a7ab993-afa3-4a29-9b0b-f64583a4d888/oauth2/token&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…signed with the private key of the certificate provided to the Azure AD App registration.&lt;/p&gt;
&lt;p&gt;The jwt contains the following claims:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“iat”: Issued at timestamp&lt;/li&gt;
&lt;li&gt;“exp”: Expires timestamp - time window, as short as possible&lt;/li&gt;
&lt;li&gt;“iss”: Issuer - the App Id&lt;/li&gt;
&lt;li&gt;“sub”: Subject Claim - also the App Id&lt;/li&gt;
&lt;li&gt;“aud”: Audience - the token endpoint&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is quite hard to do with command line tools, fortunately there is a handy npm package that does all that in one step:&lt;/p&gt;
&lt;h2 id=&quot;the-jwtgen-tool&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;the jwtgen tool&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#the-jwtgen-tool&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The &lt;code&gt;jwtgen&lt;/code&gt; Tool&lt;/h2&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; jwtgen&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -a&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; RS256&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         -p&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; key.pem&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         -e&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 3600&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         -c&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;iss=&amp;#x3C;client-id&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         -c&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;sub=&amp;#x3C;client-id&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         -c&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;aud=https://login.microsoftonline.com/&amp;#x3C;tenant-id&gt;/oauth2/token&quot;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         --headers&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;{&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;typ&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;JWT&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;alg&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;RS256&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;x5t&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&amp;#x3C;base64-encoded-certificate-thumbprint&gt;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;}&quot;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         -v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the certificate thumbprint &lt;code&gt;&amp;#x3C;base64-encoded-certificate-thumbprint&gt;&lt;/code&gt; usually comes in a hexadecimal representatation, e.g. &lt;code&gt;49AF595AE9C628BCAF5AB9D36B4EEC97DFF24458&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Sites like &lt;a href=&quot;https://base64.guru/converter/encode/hex&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Base64.guru&lt;/a&gt; or &lt;a href=&quot;https://gchq.github.io/CyberChef/#recipe=From_Hex(&amp;#x27;Auto&amp;#x27;)To_Base64(&amp;#x27;A-Za-z0-9%2B/%3D&amp;#x27;)&amp;#x26;input=NDlBRjU5NUFFOUM2MjhCQ0FGNUFCOUQzNkI0RUVDOTdERkYyNDQ1OA&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;this CyberChef recipe&lt;/a&gt; can be used to get the correct base 64 encoded representation of the certificate thumbprint: &lt;code&gt;Sa9ZWunGKLyvWrnTa07sl9/yRFg=&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;everything-put-together&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;everything put together&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#everything-put-together&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Everything put together&lt;/h2&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; jwtgen&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -a&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; RS256&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         -p&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; key.pem&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         -e&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 3600&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         -c&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;iss=791ff0ac-1f93-47fc-8629-6b20f360036f&quot;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         -c&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;sub=791ff0ac-1f93-47fc-8629-6b20f360036f&quot;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         -c&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;aud=https://login.microsoftonline.com/0a7ab993-afa3-4a29-9b0b-f64583a4d888/oauth2/token&quot;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         --headers&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;{&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;typ&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;JWT&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;alg&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;RS256&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;x5t&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;Sa9ZWunGKLyvWrnTa07sl9/yRFg=&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;}&quot;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;         -v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;-v&lt;/code&gt; commandline option produces verbose output including the encoded claims, headers and the token:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;algorithm:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; RS256&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;claims:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  &quot;iat&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 1678549167,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  &quot;exp&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 1678552767,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  &quot;iss&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;791ff0ac-1f93-47fc-8629-6b20f360036f&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  &quot;sub&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;791ff0ac-1f93-47fc-8629-6b20f360036f&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  &quot;aud&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;https://login.microsoftonline.com/0a7ab993-afa3-4a29-9b0b-f64583a4d888/oauth2/token&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;headers:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  &quot;typ&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;JWT&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  &quot;alg&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;RS256&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  &quot;x5t&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;Sa9ZWunGKLyvWrnTa07sl9/yRFg=&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;token:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1....&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; many&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; more&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; characters&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using the client assertion - shown in the token field - we can now try to request a token from the aouth2 token endpoint:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;http&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;POST&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; https://login.microsoftonline.com:443/0a7ab993-afa3-4a29-9b0b-f64583a4d888/oauth2/v2.0/token&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Content-Type&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; application/x-www-form-urlencoded&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;client_id=791ff0ac-1f93-47fc-8629-6b20f360036f&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;grant_type&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;client_credentials&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;scope&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;https://loitzl.sharepoint.com/.default&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;client_assertion&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1......&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;client_assertion_type&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;urn:ietf:params:oauth:client-assertion-type:jwt-bearer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Et voilà, we (hopefully) got a valid &lt;code&gt;access_token&lt;/code&gt; in the response:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;  &quot;token_type&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;Bearer&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;  &quot;expires_in&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;3599&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;  &quot;ext_expires_in&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;3599&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;  &quot;access_token&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1d....&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lets try this by…&lt;/p&gt;
&lt;h1 id=&quot;getting-all-lists-from-a-sharepoint-site-using-the-rest-api&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;getting all lists from a sharepoint site using the rest api&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#getting-all-lists-from-a-sharepoint-site-using-the-rest-api&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Getting all Lists from a SharePoint Site using the REST API&lt;/h1&gt;
&lt;p&gt;Using the token requested using a client assertion we can now try to get all lists from my SharePoint root site:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;http&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;GET&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; https://loitzl.sharepoint.com/_api/web/lists&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Accept&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; application/json;odata=verbose&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Authorization&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Bearer eyJ0eXAiOiJKV1QiLCJhbGciOi....&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The result: the first couple of fields of the &lt;code&gt;/lists&lt;/code&gt; request.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;  &quot;d&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;results&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &quot;__metadata&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;          &quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;https://loitzl.sharepoint.com/_api/Web/SiteUserInfoList&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;          &quot;uri&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;https://loitzl.sharepoint.com/_api/Web/SiteUserInfoList&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;          &quot;etag&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;82&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;          &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;SP.List&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;        },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &quot;FirstUniqueAncestorSecurableObject&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;✅ Yess!&lt;/p&gt;
&lt;h1 id=&quot;using-a-client-secret&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;using a client secret&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#using-a-client-secret&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Using a client secret&lt;/h1&gt;
&lt;p&gt;My IT department asked me if it’s possible to use a client secret instead, so I tried this as well.&lt;/p&gt;
&lt;p&gt;The token endpoint request:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;http&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;POST&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; https://login.microsoftonline.com:443/0a7ab993-afa3-4a29-9b0b-f64583a4d888/oauth2/v2.0/token&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Content-Type&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; application/x-www-form-urlencoded&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;client_id=791ff0ac-1f93-47fc-8629-6b20f360036f&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;grant_type&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;client_credentials&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;scope&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;https://loitzl.sharepoint.com/.default&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;client_secret&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;tdB8Q....&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;returns an access token as well:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;  &quot;token_type&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;Bearer&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;  &quot;expires_in&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;3599&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;  &quot;ext_expires_in&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;3599&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;  &quot;access_token&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJS....&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If we use that token on the SharePoint REST API…&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;http&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;GET&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; https://loitzl.sharepoint.com/_api/web/lists&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Accept&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; application/json;odata=verbose&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Authorization&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSU...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…it replies with an “401 Unauthorized”:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Unsupported app only token.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;structure-of-the-bearer-token&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;structure of the bearer token&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#structure-of-the-bearer-token&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Structure of the Bearer Token&lt;/h2&gt;
&lt;p&gt;The bearer token acquired with a client assertion contains an &lt;code&gt;appidacr&lt;/code&gt; claim with a value of &lt;code&gt;2&lt;/code&gt;, the client secret acquired token has an &lt;code&gt;appidacr&lt;/code&gt; value of &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/320.webp 320w, /generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/480.webp 480w, /generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/640.webp 640w, /generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/750.webp 750w, /generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/828.webp 828w, /generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/960.webp 960w, /generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/1167.webp 1167w&quot; sizes=&quot;(min-width: 1167px) 1167px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;ClientAssertion vs ClientSecret Token&quot; src=&quot;/generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/1167.png&quot; srcset=&quot;/generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/320.png 320w, /generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/480.png 480w, /generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/640.png 640w, /generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/750.png 750w, /generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/828.png 828w, /generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/960.png 960w, /generated/ClientAssertion-vs-ClientSecret-Token-da8f3a3c/1167.png 1167w&quot; sizes=&quot;(min-width: 1167px) 1167px, 100vw&quot; width=&quot;1167&quot; height=&quot;566&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;I reckon that SharePoint uses this value to distinguish if the endpoint accepts the token or not.&lt;/p&gt;
&lt;h1 id=&quot;conclusion&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;conclusion&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#conclusion&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;In my opinion signed client assertions are a more secure method for getting bearer tokens than using client secrets (regardless of SharePoint).&lt;/p&gt;
&lt;p&gt;If someone gets hold of the client secret in transport, the window of compromise is as long as the validity duration of the client secret (thus keep them as short as possible).&lt;/p&gt;
&lt;p&gt;But if we lose a client assertion in transport, its only valid for the requested duration, probably just a couple of minutes or even seconds.&lt;/p&gt;
&lt;p&gt;Nevertheless, we need to handle the certificate, which is another topic.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💙&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;references&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;references&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#references&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Azure AD Token Generation using a Certificate Secret Client Credentials Flow. &lt;a href=&quot;https://gist.github.com/phillipharding/d6cc4b84221cf5304e41d97beb62ea6c&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Philip Harding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Doing the same thing in .Net Core. &lt;a href=&quot;https://blog.mastykarz.nl/azure-ad-app-only-access-token-using-certificate-dotnet-core/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Waldek Mastykarz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pexels.com/photo/robot-holding-a-red-flower-8438966/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Photo by Pavel Danilyuk&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc7523&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title type="html">Getting a Term using a Custom Property Value with PnP Core</title>
    <link href="https://blog.loitzl.com/posts/getting-term-using-custom-a-property-value-with-pnpcore" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/getting-term-using-custom-a-property-value-with-pnpcore</id>
    <updated>2022-11-08T11:11:11.000Z</updated>
    <summary type="html">A term in SharePoint Taxonomies can have custom properties. PnP Core has now the ability to query terms by custom property value.</summary>
    <content type="html">&lt;p&gt;&lt;img alt=&quot;Logo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;321&quot; height=&quot;140&quot; src=&quot;/_astro/logo.CmFiv0WG_VpKLY.svg&quot;&gt;&lt;/p&gt;
&lt;h1 id=&quot;objective&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;objective&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#objective&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Objective&lt;/h1&gt;
&lt;p&gt;A nice feature of SharePoint Managed Metadata is the possibility to store custom key-value pairs as “Shared custom properties” on terms.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/TermCustomProperty-eae4bf73/320.webp 320w, /generated/TermCustomProperty-eae4bf73/480.webp 480w, /generated/TermCustomProperty-eae4bf73/640.webp 640w, /generated/TermCustomProperty-eae4bf73/750.webp 750w, /generated/TermCustomProperty-eae4bf73/828.webp 828w, /generated/TermCustomProperty-eae4bf73/960.webp 960w, /generated/TermCustomProperty-eae4bf73/1762.webp 1762w&quot; sizes=&quot;(min-width: 1762px) 1762px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;TermCustomProperty&quot; src=&quot;/generated/TermCustomProperty-eae4bf73/1762.png&quot; srcset=&quot;/generated/TermCustomProperty-eae4bf73/320.png 320w, /generated/TermCustomProperty-eae4bf73/480.png 480w, /generated/TermCustomProperty-eae4bf73/640.png 640w, /generated/TermCustomProperty-eae4bf73/750.png 750w, /generated/TermCustomProperty-eae4bf73/828.png 828w, /generated/TermCustomProperty-eae4bf73/960.png 960w, /generated/TermCustomProperty-eae4bf73/1762.png 1762w&quot; sizes=&quot;(min-width: 1762px) 1762px, 100vw&quot; width=&quot;1762&quot; height=&quot;994&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Using the &lt;a href=&quot;https://pnp.github.io/pnpcore/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PnP Core SDK&lt;/a&gt; they are also easy to add programatically:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// Add a term set&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; termSet &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; group&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Sets&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AddAsync&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;PnPSet1&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;Set description&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// Add a term&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; newTerm &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; termSet&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Terms&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AddAsync&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;T1&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;Description in English&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// Add a custom property with key and value&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;newTerm&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AddProperty&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;property1&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;value1&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// Commit changes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;await&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; newTerm&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;UpdateAsync&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I used this feature a lot to create hierarchical structures, e.g. for tree like site collection navigation.
Each site collection url is stored as a custom property on the corresponding term.&lt;/p&gt;
&lt;p&gt;Simple as that.&lt;/p&gt;
&lt;p&gt;The concept is so generic that it opens up a lot of other possibilities, e.g. the key-value pairs do not have to be unique, so it can also be used for categories or classification, etc.&lt;/p&gt;
&lt;h1 id=&quot;retrieving-terms-using-custom-properties&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;retrieving terms using custom properties&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#retrieving-terms-using-custom-properties&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Retrieving Terms using custom properties&lt;/h1&gt;
&lt;p&gt;A new feature of the &lt;a href=&quot;https://pnp.github.io/pnpcore/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PnP Core SDK&lt;/a&gt; comes with &lt;a href=&quot;https://pnp.github.io/blog/pnp-core-sdk/pnp-core-sdk-v1-8/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PnP Core SDK v1.8&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Add ITermSet.GetTermsByCustomProperty method to retrieve a list of terms with a certain custom property key and value&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The new method &lt;a href=&quot;https://pnp.github.io/pnpcore/api/PnP.Core.Model.SharePoint.ITermSet.html#PnP_Core_Model_SharePoint_ITermSet_GetTermsByCustomProperty_System_String_System_String_System_Boolean_&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;ITermSet.GetTermsByCustomProperty( key, value )&lt;/code&gt;&lt;/a&gt; gets a list of all &lt;code&gt;ITerm&lt;/code&gt;s containing a certain custom property key and value.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// load the terms by custom property&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; IList&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;ITerm&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; await&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; termSet&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;GetTermsByCustomProperty&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &quot;property1&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &quot;value1&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;     );&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is a section in &lt;a href=&quot;https://pnp.github.io/pnpcore/using-the-sdk/taxonomy-advanced.html#getting-terms-based-upon-their-property-values&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Working with taxonomy: advanced concepts&lt;/a&gt; giving a little bit of context around that topic.&lt;/p&gt;
&lt;p&gt;Slick 💪&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Photo in Metadata by &lt;a href=&quot;https://www.pexels.com/photo/brown-cow-3640073/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Ave Calvar Martinez&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">Retrieving Azure Application Insights using Azure CLI</title>
    <link href="https://blog.loitzl.com/posts/applicationinsights-via-az-cli" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/applicationinsights-via-az-cli</id>
    <updated>2022-04-12T23:40:32.169Z</updated>
    <summary type="html">Azure Application Insights can be retrieved using the Azure CLI. Since we can authenticate with a client secret or certificate, the logs can be retrieved by a daemon app or background job.</summary>
    <content type="html">&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/Azure-Insights-CLI-3a55fea8/320.webp 320w, /generated/Azure-Insights-CLI-3a55fea8/480.webp 480w, /generated/Azure-Insights-CLI-3a55fea8/640.webp 640w, /generated/Azure-Insights-CLI-3a55fea8/750.webp 750w, /generated/Azure-Insights-CLI-3a55fea8/760.webp 760w&quot; sizes=&quot;(min-width: 760px) 760px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Azure Insights in the CLI&quot; src=&quot;/generated/Azure-Insights-CLI-3a55fea8/760.png&quot; srcset=&quot;/generated/Azure-Insights-CLI-3a55fea8/320.png 320w, /generated/Azure-Insights-CLI-3a55fea8/480.png 480w, /generated/Azure-Insights-CLI-3a55fea8/640.png 640w, /generated/Azure-Insights-CLI-3a55fea8/750.png 750w, /generated/Azure-Insights-CLI-3a55fea8/760.png 760w&quot; sizes=&quot;(min-width: 760px) 760px, 100vw&quot; width=&quot;760&quot; height=&quot;312&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h1 id=&quot;objective&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;objective&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#objective&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Objective&lt;/h1&gt;
&lt;p&gt;Besides the Azure Insights user interface in the Azure Portal before there is also an Azure CLI extension for retrieving and querying Azure Insights data.&lt;/p&gt;
&lt;p&gt;This article describes a way how to retrieve that data in a background job or daemon application.&lt;/p&gt;
&lt;h1 id=&quot;authentication-options&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;authentication options&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#authentication-options&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Authentication Options&lt;/h1&gt;
&lt;p&gt;There are several ways to authenticate the Azure CLI using &lt;code&gt;az login&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;interactive-login&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;interactive login&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#interactive-login&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Interactive Login&lt;/h2&gt;
&lt;p&gt;If the login request is from a computer with a browser, a login window will automatically pop-up.&lt;/p&gt;
&lt;p&gt;When the cli is running in a container or remote ssh session Azure CLI will automatically fall back to device authentication:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; docker&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; run&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -v&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; ${&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;PWD&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;:/workspace&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -it&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mcr.microsoft.com/azure-cli&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[Container starts]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;bash-5.1#&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; az&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; login&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;To&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sign&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; in,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; use&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; web&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; browser&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; to&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; open&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; the&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; page&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; https://microsoft.com/devicelogin&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; and&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; enter&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; the&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; code&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; AABBCCDD5&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; to&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; authenticate.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[Sign In in Browser]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;cloudName&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;AzureCloud&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    [..]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;Visual Studio Ultimate mit MSDN&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;state&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;Enabled&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;tenantId&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;0a7ab993-afa3-4a29-9b0b-f64583a4d888&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    [..]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;bash-5.1#&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;automated-login&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;automated login&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#automated-login&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Automated Login&lt;/h2&gt;
&lt;p&gt;For automation purposes it can be necessary to authenticate within azure cli using a client secret…&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; az&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; login&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  --service-principal&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -u&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; c4fe6c64-4e6a-4997-9a4f-7d96b30dfb51&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \ &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; App&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  -p&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; iNr....GaaNE&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \ &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Client&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Secret&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  --tenant&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 0a7ab993-afa3-4a29-9b0b-f64583a4d888&lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt; # Tenant id or name&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…or with a client certificate in pem format:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; az&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; login&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  --service-principal&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -u&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; c4fe6c64-4e6a-4997-9a4f-7d96b30dfb51&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \ &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; App&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Id&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  -p&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ClientCert.pem&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \ &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Client&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Certificate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  --tenant&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 0a7ab993-afa3-4a29-9b0b-f64583a4d888&lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt; # Tenant id or name&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Information on how to obtain a certificate in pem format using &lt;code&gt;openssl&lt;/code&gt; can be found &lt;a href=&quot;/posts/creating-sharePoint-managed-metadata-terms-using-the-new-pnp-core-sdk/#setup-authentication&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&quot;find-the-azure-insights-resource&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;find the azure insights resource&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#find-the-azure-insights-resource&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Find the Azure Insights Resource&lt;/h1&gt;
&lt;p&gt;Now we can try to find the correct azure insights resource.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;az group list&lt;/code&gt; resource groups where the service principal has access can be listed.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; az&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; group&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; list&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{ [..] },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    &quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;/subscriptions/4664bbed-abef-4e8b-bd4a-462f757c712c/resourceGroups/rg-dev&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    &quot;location&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;switzerlandnorth&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    &quot;managedBy&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; null,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;dev&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    &quot;properties&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;      &quot;provisioningState&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;Succeeded&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    &quot;tags&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; null,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;Microsoft.Resources/resourceGroups&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{ [..] },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{ [..] }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When the resource group name is known we can list the contents of a resource group using &lt;code&gt;az resource list&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; az&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; resource&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; list&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  --resource-group&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; rg-dev&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \ &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;#&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; the&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; resource&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; group&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; the&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; previous&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; step&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  --resource-type&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Microsoft.Insights/components&lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt; # azure insights type&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;changedTime&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;2022-02-24T10:17:15.282736+00:00&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;createdTime&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;2022-02-24T10:07:14.668422+00:00&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;extendedLocation&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: null,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;/subscriptions/4664bbed-abef-4e8b-bd4a-462f757c712c/resourceGroups/rg-dev/providers/Microsoft.Insights/components/dev&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;identity&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: null,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;kind&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;web&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;location&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;switzerlandnorth&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;managedBy&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: null,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;dev&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;plan&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: null,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;properties&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: null,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;provisioningState&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;Succeeded&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;resourceGroup&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;rg-dev&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;sku&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: null,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;tags&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;Microsoft.Insights/components&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The value of the &lt;code&gt;id&lt;/code&gt; can be used to retrieve monitoring events.&lt;/p&gt;
&lt;h1 id=&quot;retrieving-events&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;retrieving events&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#retrieving-events&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Retrieving Events&lt;/h1&gt;
&lt;p&gt;Using &lt;code&gt;az monitor app-insights events&lt;/code&gt; we can now retrieve events from Azure Insights by passing the &lt;code&gt;id&lt;/code&gt; retrieved in the previous step as the &lt;code&gt;--app&lt;/code&gt; parameter.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; az&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; monitor&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; app-insights&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; events&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; show&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  --app&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /subscriptions/4664bbed-abef-4e8b-bd4a-462f757c712c/resourceGroups/rg-dev/providers/Microsoft.Insights/components/dev&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  --type&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; traces&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  --offset&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 24h&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Setting the &lt;code&gt;--offset&lt;/code&gt; parameter will retrieve application traces within the last 24 hours.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{[..]},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      &quot;ai&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &quot;appName&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;dev&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &quot;sdkVersion&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;azurefunctions: 3.5.2.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;        [..]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      &quot;application&quot;: {[..]},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      &quot;client&quot;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;        [..],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;        &quot;type&quot;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;PC&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      &quot;cloud&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &quot;roleInstance&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;...&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &quot;roleName&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;dev&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      &quot;count&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      &quot;customDimensions&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: { [..] },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      &quot;customMeasurements&quot;: &lt;/span&gt;&lt;span style=&quot;color:#B58900&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      &quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;dbf73851-ba43-11ec-a27c-af008d3d954f&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      &quot;operation&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;PeopleSyncJob&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &quot;parentId&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;2bd1380092e0fd47&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;        [..]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      &quot;session&quot;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      &quot;timestamp&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;2022-04-12T09:35:02.767000+00:00&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      &quot;trace&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &quot;message&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;🍰 i:0#.f|membership|gradya@loitzl1.onmicrosoft.com&apos;s Birthday: &apos;3/8/2000 12:00:00 AM&apos;&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &quot;severityLevel&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;trace&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      &quot;user&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: {[..]}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{[..]},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{[..]}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The field &lt;code&gt;trace.message&lt;/code&gt; contains the custom log entry we might be interested in.&lt;/p&gt;
&lt;h1 id=&quot;executing-analytics-queries&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;executing analytics queries&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#executing-analytics-queries&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Executing Analytics Queries&lt;/h1&gt;
&lt;p&gt;It is also possible to run &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;kusto queries&lt;/a&gt; within Azure CLI using &lt;code&gt;az monitor app-insights query&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; az&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; monitor&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; app-insights&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; query&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  --app&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; fc162434-7ef9-4d1c-a9d7-3ac820c38800&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  --offset&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 24h&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  --analytics-query&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &apos;traces | search &quot;*grady*&quot;&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This returns a json table structure&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  &quot;tables&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;      &quot;columns&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#DC322F&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;      &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;PrimaryResult&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;      &quot;rows&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color:#DC322F&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;where &lt;code&gt;columns&lt;/code&gt; contains a description of the row’s data,&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt; &quot;columns&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;   {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;     &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;$table&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;     &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;   },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;   {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;     &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;timestamp&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;     &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;datetime&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;   },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;   {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;     &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;message&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;     &quot;type&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;   },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;   [&lt;/span&gt;&lt;span style=&quot;color:#DC322F&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and &lt;code&gt;rows&lt;/code&gt; contains the actual data:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;json&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   &quot;traces&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   &quot;2022-04-11T16:00:02.770299Z&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   &quot;🍰 i:0#.f|membership|gradya@loitzl1.onmicrosoft.com&apos;s Birthday: &apos;3/8/2000 12:00:00 AM&apos;&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;   [&lt;/span&gt;&lt;span style=&quot;color:#DC322F&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;correlate-log-entries&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;correlate log entries&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#correlate-log-entries&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Correlate Log entries&lt;/h2&gt;
&lt;p&gt;If we have something that can be used to correlate log entries over one request or operation, a full trace can be retrieved like this:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; az&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; monitor&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; app-insights&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; query&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  --app&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; fc162434-7ef9-4d1c-a9d7-3ac820c38800&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  --offset&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 24h&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  --analytics-query&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &apos;traces | where customDimensions.prop__SyncPropertiesId == &quot;76b036f3-3083-4472-8958-171c46fb8e02&quot;&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;together with the magic of &lt;a href=&quot;https://stedolan.github.io/jq/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;jq&lt;/code&gt;&lt;/a&gt; we can transform the result into a complete trace of a certain operation:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ...&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; jq&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &apos;.tables[0] | .rows | .[][1]&apos;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;Syncing user &apos;GradyA@loitzl1.onmicrosoft.com&apos;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;Creating ACSAppOnlyContext for &apos;https://loitzl1-admin.sharepoint.com&apos; and &apos;eca24dc1-1e18-4ed0-94b7-f9c269caf540&apos;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;✔ Successfully resolved &apos;i:0#.f|membership|gradya@loitzl1.onmicrosoft.com&apos;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;Users Country &apos;Switzerland&apos;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;🍰 i:0#.f|membership|gradya@loitzl1.onmicrosoft.com&apos;s Birthday: &apos;3/8/2000 12:00:00 AM&apos;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&quot;✔ Successfully synced user &apos;i:0#.f|membership|gradya@loitzl1.onmicrosoft.com&apos;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;outlook&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;outlook&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#outlook&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Outlook&lt;/h1&gt;
&lt;p&gt;Being able to retrieve and analyze Azure Insights data as a daemon app brings interesting opportunities for log analytics and alerting.&lt;/p&gt;
&lt;p&gt;It could also be used for higher level integration testing in projects with a low level of testability.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">Syncing MS Graph Properties with SharePoint User Profile from Azure Function</title>
    <link href="https://blog.loitzl.com/posts/graph-userprofilesync-with-azure-function" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/graph-userprofilesync-with-azure-function</id>
    <updated>2022-03-16T23:40:32.169Z</updated>
    <summary type="html">In SharePoint Online only a predefined set of properties gets synchronized from the Azure Active Directory User object to the SharePoint User Profile. This article shows how to add additional User Profile properties using a timer-triggered Azure Function and surface them in SharePoin Search.</summary>
    <content type="html">&lt;p&gt;Azure Active Directory
&lt;picture&gt;&lt;source srcset=&quot;/generated/Graph-Erdbeerland-bfe1e0f5/320.webp 320w, /generated/Graph-Erdbeerland-bfe1e0f5/480.webp 480w, /generated/Graph-Erdbeerland-bfe1e0f5/640.webp 640w, /generated/Graph-Erdbeerland-bfe1e0f5/750.webp 750w, /generated/Graph-Erdbeerland-bfe1e0f5/828.webp 828w, /generated/Graph-Erdbeerland-bfe1e0f5/960.webp 960w, /generated/Graph-Erdbeerland-bfe1e0f5/1120.webp 1120w&quot; sizes=&quot;(min-width: 1120px) 1120px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Graph: Erdbeerland&quot; src=&quot;/generated/Graph-Erdbeerland-bfe1e0f5/1120.png&quot; srcset=&quot;/generated/Graph-Erdbeerland-bfe1e0f5/320.png 320w, /generated/Graph-Erdbeerland-bfe1e0f5/480.png 480w, /generated/Graph-Erdbeerland-bfe1e0f5/640.png 640w, /generated/Graph-Erdbeerland-bfe1e0f5/750.png 750w, /generated/Graph-Erdbeerland-bfe1e0f5/828.png 828w, /generated/Graph-Erdbeerland-bfe1e0f5/960.png 960w, /generated/Graph-Erdbeerland-bfe1e0f5/1120.png 1120w&quot; sizes=&quot;(min-width: 1120px) 1120px, 100vw&quot; width=&quot;1120&quot; height=&quot;201&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;
SharePoint User Profile
&lt;picture&gt;&lt;source srcset=&quot;/generated/UserProfile-Erdbeerland-bfe1e0f5/320.webp 320w, /generated/UserProfile-Erdbeerland-bfe1e0f5/480.webp 480w, /generated/UserProfile-Erdbeerland-bfe1e0f5/640.webp 640w, /generated/UserProfile-Erdbeerland-bfe1e0f5/750.webp 750w, /generated/UserProfile-Erdbeerland-bfe1e0f5/762.webp 762w&quot; sizes=&quot;(min-width: 762px) 762px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;UserProfile: Erdbeerland&quot; src=&quot;/generated/UserProfile-Erdbeerland-bfe1e0f5/762.png&quot; srcset=&quot;/generated/UserProfile-Erdbeerland-bfe1e0f5/320.png 320w, /generated/UserProfile-Erdbeerland-bfe1e0f5/480.png 480w, /generated/UserProfile-Erdbeerland-bfe1e0f5/640.png 640w, /generated/UserProfile-Erdbeerland-bfe1e0f5/750.png 750w, /generated/UserProfile-Erdbeerland-bfe1e0f5/762.png 762w&quot; sizes=&quot;(min-width: 762px) 762px, 100vw&quot; width=&quot;762&quot; height=&quot;60&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;font size=&quot;7&quot;&gt;🍓&lt;/font&gt;&lt;/p&gt;
&lt;h1 id=&quot;introduction&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;introduction&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#introduction&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Introduction&lt;/h1&gt;
&lt;p&gt;In SharePoint Online only syncs a &lt;a href=&quot;https://docs.microsoft.com/en-us/sharepoint/user-profile-sync&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;predefined set of properties&lt;/a&gt; from an Azure Active Directory User object to the SharePoint UserProfile and as mentioned in the &lt;a href=&quot;(https://docs.microsoft.com/en-us/sharepoint/user-profile-sync#frequentlyasked-questions-faqs)&quot;&gt;FAQ&lt;/a&gt; section &lt;strong&gt;no&lt;/strong&gt; additional properties can be added.&lt;/p&gt;
&lt;p&gt;But it is still possible to add new &lt;a href=&quot;https://docs.microsoft.com/en-us/sharepoint/add-and-edit-user-profile-properties&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;User Profile Properties&lt;/a&gt; in SharePoint Online.&lt;/p&gt;
&lt;p&gt;The newly created property becomes a Crawled Property and can be mapped to a Managed Property and surfaced in the &lt;a href=&quot;https://docs.microsoft.com/en-us/sharepoint/manage-search-schema&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SharePoint Online Search Schema&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Using a timer-triggered Azure Function it is possible to synchronize Azure Active Directory properties of a user object (or anything else) with the SharePoint Online User Profile.&lt;/p&gt;
&lt;p&gt;This example shows how to get the ‘Country or Region’ property of the AAD User object synced with a SharePoint User Profile custom property and a Managed Property in SharePoint Online Search.&lt;/p&gt;
&lt;h1 id=&quot;creating-the-user-profile-property&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;creating the user profile property&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#creating-the-user-profile-property&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Creating the User Profile Property&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Navigate to SharePoint Admin Center -&gt; More Features -&gt; User Profiles&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;https://&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;tenant&gt;-admin.sharepoint.com/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;      _layouts/15/TenantProfileAdmin/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;           ManageUserProfileServiceApplication.aspx&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Click “Manage User Properties”&lt;/li&gt;
&lt;li&gt;Add a “New Property”&lt;/li&gt;
&lt;li&gt;Give it a name&lt;/li&gt;
&lt;li&gt;Be sure that the “Default Privacy Setting” is set to “Everyone”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/UserProfile-Name-Everyone-bfe1e0f5/320.webp 320w, /generated/UserProfile-Name-Everyone-bfe1e0f5/480.webp 480w, /generated/UserProfile-Name-Everyone-bfe1e0f5/640.webp 640w, /generated/UserProfile-Name-Everyone-bfe1e0f5/750.webp 750w, /generated/UserProfile-Name-Everyone-bfe1e0f5/828.webp 828w, /generated/UserProfile-Name-Everyone-bfe1e0f5/960.webp 960w, /generated/UserProfile-Name-Everyone-bfe1e0f5/982.webp 982w&quot; sizes=&quot;(min-width: 982px) 982px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;UserProfile: Name, Everyone&quot; src=&quot;/generated/UserProfile-Name-Everyone-bfe1e0f5/982.png&quot; srcset=&quot;/generated/UserProfile-Name-Everyone-bfe1e0f5/320.png 320w, /generated/UserProfile-Name-Everyone-bfe1e0f5/480.png 480w, /generated/UserProfile-Name-Everyone-bfe1e0f5/640.png 640w, /generated/UserProfile-Name-Everyone-bfe1e0f5/750.png 750w, /generated/UserProfile-Name-Everyone-bfe1e0f5/828.png 828w, /generated/UserProfile-Name-Everyone-bfe1e0f5/960.png 960w, /generated/UserProfile-Name-Everyone-bfe1e0f5/982.png 982w&quot; sizes=&quot;(min-width: 982px) 982px, 100vw&quot; width=&quot;982&quot; height=&quot;860&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Be sure that in “Search Settings” the checkbox “Indexed” is set&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/UserProfile-Indexed-bfe1e0f5/320.webp 320w, /generated/UserProfile-Indexed-bfe1e0f5/480.webp 480w, /generated/UserProfile-Indexed-bfe1e0f5/640.webp 640w, /generated/UserProfile-Indexed-bfe1e0f5/750.webp 750w, /generated/UserProfile-Indexed-bfe1e0f5/828.webp 828w, /generated/UserProfile-Indexed-bfe1e0f5/960.webp 960w, /generated/UserProfile-Indexed-bfe1e0f5/1084.webp 1084w&quot; sizes=&quot;(min-width: 1084px) 1084px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;UserProfile: Indexed&quot; src=&quot;/generated/UserProfile-Indexed-bfe1e0f5/1084.png&quot; srcset=&quot;/generated/UserProfile-Indexed-bfe1e0f5/320.png 320w, /generated/UserProfile-Indexed-bfe1e0f5/480.png 480w, /generated/UserProfile-Indexed-bfe1e0f5/640.png 640w, /generated/UserProfile-Indexed-bfe1e0f5/750.png 750w, /generated/UserProfile-Indexed-bfe1e0f5/828.png 828w, /generated/UserProfile-Indexed-bfe1e0f5/960.png 960w, /generated/UserProfile-Indexed-bfe1e0f5/1084.png 1084w&quot; sizes=&quot;(min-width: 1084px) 1084px, 100vw&quot; width=&quot;1084&quot; height=&quot;79&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h1 id=&quot;creating-the-search-managed-property&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;creating the search managed property&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#creating-the-search-managed-property&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Creating the Search Managed Property&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Navigate to SharePoint Admin Center -&gt; More Features -&gt; Search&lt;/li&gt;
&lt;li&gt;Click “Manage Search Schema”&lt;/li&gt;
&lt;li&gt;Select “Managed Properties”&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;https://&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;tenant&gt;-admin.sharepoint.com/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;       _layouts/15/searchadmin/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;           ta_listmanagedproperties.aspx?level&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;=tenant&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Look for an existing “RefineableStringXYZ” (I used “RefinableString120” in this example)&lt;/li&gt;
&lt;li&gt;Add an Alias, e.g., CountryOrRegion&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/ManagedProperty-Alias-bfe1e0f5/320.webp 320w, /generated/ManagedProperty-Alias-bfe1e0f5/480.webp 480w, /generated/ManagedProperty-Alias-bfe1e0f5/591.webp 591w&quot; sizes=&quot;(min-width: 591px) 591px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;ManagedProperty: Alias&quot; src=&quot;/generated/ManagedProperty-Alias-bfe1e0f5/591.png&quot; srcset=&quot;/generated/ManagedProperty-Alias-bfe1e0f5/320.png 320w, /generated/ManagedProperty-Alias-bfe1e0f5/480.png 480w, /generated/ManagedProperty-Alias-bfe1e0f5/591.png 591w&quot; sizes=&quot;(min-width: 591px) 591px, 100vw&quot; width=&quot;591&quot; height=&quot;269&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Click “Add a Mapping” to map the Crawled Property “People:CustomCountry” on the “Managed Property”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/ManagedProperty-mapped-bfe1e0f5/320.webp 320w, /generated/ManagedProperty-mapped-bfe1e0f5/480.webp 480w, /generated/ManagedProperty-mapped-bfe1e0f5/640.webp 640w, /generated/ManagedProperty-mapped-bfe1e0f5/750.webp 750w, /generated/ManagedProperty-mapped-bfe1e0f5/828.webp 828w, /generated/ManagedProperty-mapped-bfe1e0f5/922.webp 922w&quot; sizes=&quot;(min-width: 922px) 922px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;ManagedProperty-mapped&quot; src=&quot;/generated/ManagedProperty-mapped-bfe1e0f5/922.png&quot; srcset=&quot;/generated/ManagedProperty-mapped-bfe1e0f5/320.png 320w, /generated/ManagedProperty-mapped-bfe1e0f5/480.png 480w, /generated/ManagedProperty-mapped-bfe1e0f5/640.png 640w, /generated/ManagedProperty-mapped-bfe1e0f5/750.png 750w, /generated/ManagedProperty-mapped-bfe1e0f5/828.png 828w, /generated/ManagedProperty-mapped-bfe1e0f5/922.png 922w&quot; sizes=&quot;(min-width: 922px) 922px, 100vw&quot; width=&quot;922&quot; height=&quot;230&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;
&lt;picture&gt;&lt;source srcset=&quot;/generated/CrawledProperty-Mapping-bfe1e0f5/320.webp 320w, /generated/CrawledProperty-Mapping-bfe1e0f5/480.webp 480w, /generated/CrawledProperty-Mapping-bfe1e0f5/608.webp 608w&quot; sizes=&quot;(min-width: 608px) 608px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;CrawledProperty-Mapping&quot; src=&quot;/generated/CrawledProperty-Mapping-bfe1e0f5/608.png&quot; srcset=&quot;/generated/CrawledProperty-Mapping-bfe1e0f5/320.png 320w, /generated/CrawledProperty-Mapping-bfe1e0f5/480.png 480w, /generated/CrawledProperty-Mapping-bfe1e0f5/608.png 608w&quot; sizes=&quot;(min-width: 608px) 608px, 100vw&quot; width=&quot;608&quot; height=&quot;350&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: It may take several hours for the Crawled Property “People:CustomCountry” to show up.&lt;/p&gt;
&lt;h1 id=&quot;setup-authentication-for-the-azure-function&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;setup authentication for the azure function&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#setup-authentication-for-the-azure-function&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Setup Authentication for the Azure Function&lt;/h1&gt;
&lt;p&gt;This topic is addressed in another article &lt;a href=&quot;/posts/creating-sharePoint-managed-metadata-terms-using-the-new-pnp-core-sdk/#setup-authentication&quot;&gt;Creating SharePoint Terms using the App Context with the new PnP Core SDK&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A PowerShell Script can be found in the &lt;a href=&quot;https://github.com/mloitzl/azurefunctionsprofilesync/blob/main/Configure.ps1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Github Repository&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;the-azure-function&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;the azure function&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#the-azure-function&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Azure Function&lt;/h1&gt;
&lt;p&gt;The Azure Function implementation that synchronizes the “Country or Region” property can be found in this &lt;a href=&quot;https://github.com/mloitzl/azurefunctionsprofilesync/blob/cf6bedb974a90ef5b824c33481f183b801b110bb/SyncCountry.cs#L32&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/previous-versions/office/sharepoint-csom/ee540627(v=office.15)&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Utility.ResolvePrincipal&lt;/code&gt;&lt;/a&gt; can be used to receive the &lt;a href=&quot;https://github.com/mloitzl/azurefunctionsprofilesync/blob/cf6bedb974a90ef5b824c33481f183b801b110bb/SyncCountry.cs#L80&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;login of the user&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; resolvedPrincipal &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  Utility&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;ResolvePrincipal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;      clientContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;      clientContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Web&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;      user&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Mail&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;      PrincipalType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;User&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;      PrincipalSource&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;All&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B58900&quot;&gt;      null&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B58900&quot;&gt;      true&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;); &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// true - as input is only the email&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;await&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; clientContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;ExecuteQueryRetryAsync&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;PrincipalInfo&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; principal &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; resolvedPrincipal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Value&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; loginName &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; principal&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;LoginName&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the &lt;code&gt;loginName&lt;/code&gt; we can then &lt;a href=&quot;https://github.com/mloitzl/azurefunctionsprofilesync/blob/cf6bedb974a90ef5b824c33481f183b801b110bb/SyncCountry.cs#L99&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;update&lt;/a&gt; the &lt;code&gt;CustomCountry&lt;/code&gt; property.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;  var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; peopleManager &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; PeopleManager&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;clientContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  peopleManager&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;SetSingleValueProfileProperty&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;      loginName&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      &quot;CustomCountry&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;,  &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// The custom UserProfile property&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;      user&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Country&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  clientContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Load&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;peopleManager&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  await&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; clientContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;ExecuteQueryRetryAsync&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;the-problem&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;the problem&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#the-problem&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Problem&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/previous-versions/office/sharepoint-csom/jj163361(v=office.15)&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;PeopleManager&lt;/code&gt;&lt;/a&gt; can be used to manage SharePoint Online UserProfile Properties.&lt;/p&gt;
&lt;p&gt;The Azure AD app registration that is used for &lt;a href=&quot;https://github.com/mloitzl/azurefunctionsprofilesync/blob/cf6bedb974a90ef5b824c33481f183b801b110bb/SyncCountry.cs#L39&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;accessing the graph&lt;/a&gt; &lt;strong&gt;cannot&lt;/strong&gt; be used to access the SharePoint User Profile.&lt;/p&gt;
&lt;p&gt;Since we are authenticating the Azure Function using the &lt;a href=&quot;https://pnp.github.io/pnpcore/api/PnP.Core.Auth.X509CertificateAuthenticationProvider.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PnP Core SDK&lt;/a&gt; we can use &lt;a href=&quot;https://docs.microsoft.com/en-us/answers/questions/341294/how-to-perform-sharepoint-online-authentication-in.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PnP.Framework.AuthenticationManager.GetACSAppOnlyContext&lt;/a&gt; to get a &lt;a href=&quot;https://docs.microsoft.com/en-us/previous-versions/office/sharepoint-csom/ee538685(v=office.15)&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;ClientContext&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;  public&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; ClientContext&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; GetACSAppOnlyContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;    string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; siteUrl, &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; appId, &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; appSecret)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;appId&lt;/code&gt; and &lt;code&gt;appSecret&lt;/code&gt; required for this call are from a SharePoint Add-In Registration.&lt;/p&gt;
&lt;p&gt;So, a “proxy” SharePoint Add-In is required for that:&lt;/p&gt;
&lt;p&gt;Let’s first create a new Add-In using &lt;code&gt;AppRegNew.aspx&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    https://&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;tenant&gt;.sharepoint.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;          /_layouts/15/appregnew.aspx&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Generate Client Id - note the id for later use&lt;/li&gt;
&lt;li&gt;Generate Client Secret - note the secret for later use&lt;/li&gt;
&lt;li&gt;Title: ‘Graph SyncJob Delegate App’&lt;/li&gt;
&lt;li&gt;App Domain: “&lt;a href=&quot;http://www.localhost.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;www.localhost.com&lt;/a&gt;”&lt;/li&gt;
&lt;li&gt;Redirect URL: “&lt;a href=&quot;https://www.localhost.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.localhost.com&lt;/a&gt;”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then the permissions need to be assigned using:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  https://&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;tenant&gt;-admin.sharepoint.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;           /_layouts/15/appinv.aspx&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Enter the App Id from the previous step and click on ‘Lookup’.&lt;/li&gt;
&lt;li&gt;In the Add-Ins’s permissions request, enter the followings:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;xml&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AppPermissionRequests&lt;/span&gt;&lt;span style=&quot;color:#93A1A1&quot;&gt; AllowAppOnlyPolicy&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span style=&quot;color:#93A1A1&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AppPermissionRequest&lt;/span&gt;&lt;span style=&quot;color:#93A1A1&quot;&gt; Scope&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;http://sharepoint/social/tenant&quot;&lt;/span&gt;&lt;span style=&quot;color:#93A1A1&quot;&gt; Right&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;FullControl&quot;&lt;/span&gt;&lt;span style=&quot;color:#93A1A1&quot;&gt; /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1&quot;&gt;&amp;#x3C;/&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AppPermissionRequests&lt;/span&gt;&lt;span style=&quot;color:#93A1A1&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Click on “Create”&lt;/li&gt;
&lt;li&gt;Click on “Trust”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This will request App Only Permissions for writing to the SharePoint User Profile.&lt;/p&gt;
&lt;h1 id=&quot;enabling-app-only-authentication&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;enabling app only authentication&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#enabling-app-only-authentication&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Enabling App Only Authentication&lt;/h1&gt;
&lt;p&gt;App-Only authentication is deactivated by default, but it can be enabled with this &lt;a href=&quot;https://pnp.github.io/powershell/cmdlets/Set-PnPTenant.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PnP PowerShell&lt;/a&gt; command:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    Connect-PnPOnline&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Url https:&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;//&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;tenant&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;admin.sharepoint.com&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;DeviceLogin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    Set-PnPTenant&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;DisableCustomAppAuthentication &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#B58900&quot;&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;results&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;results&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#results&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Results&lt;/h1&gt;
&lt;p&gt;After the job ran successfully the UserProfile contains a value from the Azure AD field “Country or Region” on the SharePoint UserProfile…&lt;/p&gt;
&lt;p&gt;SharePoint User Profile
&lt;picture&gt;&lt;source srcset=&quot;/generated/UserProfile-Erdbeerland-bfe1e0f5/320.webp 320w, /generated/UserProfile-Erdbeerland-bfe1e0f5/480.webp 480w, /generated/UserProfile-Erdbeerland-bfe1e0f5/640.webp 640w, /generated/UserProfile-Erdbeerland-bfe1e0f5/750.webp 750w, /generated/UserProfile-Erdbeerland-bfe1e0f5/762.webp 762w&quot; sizes=&quot;(min-width: 762px) 762px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;UserProfile: Erdbeerland&quot; src=&quot;/generated/UserProfile-Erdbeerland-bfe1e0f5/762.png&quot; srcset=&quot;/generated/UserProfile-Erdbeerland-bfe1e0f5/320.png 320w, /generated/UserProfile-Erdbeerland-bfe1e0f5/480.png 480w, /generated/UserProfile-Erdbeerland-bfe1e0f5/640.png 640w, /generated/UserProfile-Erdbeerland-bfe1e0f5/750.png 750w, /generated/UserProfile-Erdbeerland-bfe1e0f5/762.png 762w&quot; sizes=&quot;(min-width: 762px) 762px, 100vw&quot; width=&quot;762&quot; height=&quot;60&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;… and in Search, we have the &lt;code&gt;RefinableString120&lt;/code&gt; property with the same value.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Submit-PnPSearchQuery&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;SourceId b09a7990&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;05ea&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;4af9&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;81ef&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;edfab16c4e31       &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# User Profiles              `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Query &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;DocId:17592245537205&quot;&lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;                        # My Account in this Tenant  `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;SelectProperties RefinableString120&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;CountryOrRegion &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# mapped to CustomCountry    `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;).ResultRows&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Key&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                      Value&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;---&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;                      -----&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;RefinableString120&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;       Erdbeerland&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;CountryOrRegion&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;          Erdbeerland&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;DocId&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;                    17592245537205&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;GeoLocationSource&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        EUR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;contentclass&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;             urn:content-class:SPSPeople&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AccountName&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;              i:0#.f&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;membership&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;martin@loitzl.onmicrosoft.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Department&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;               Development&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;JobTitle&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                 Developer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;LastModifiedTime&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;         03/17/2022&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 09:54:21&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Path&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                     https://loitzl-my.sharepoint.com/Person.aspx?accountname=i:0%23.f&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;membership&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;martin@loitzl.onmicrosoft.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;PictureURL&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;               https://loitzl-my.sharepoint.com/User&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Photos/Profile&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Pictures/martin_loitzl_onmicrosoft_com_MThumb.jpg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;PreferredName&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;            Martin&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Loitzl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;SipAddress&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;               martin@loitzl.onmicrosoft.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;WorkEmail&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                martin@loitzl.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Title&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                    Martin&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Loitzl&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/SearchQueryTool-SearchResult-bfe1e0f5/320.webp 320w, /generated/SearchQueryTool-SearchResult-bfe1e0f5/480.webp 480w, /generated/SearchQueryTool-SearchResult-bfe1e0f5/640.webp 640w, /generated/SearchQueryTool-SearchResult-bfe1e0f5/750.webp 750w, /generated/SearchQueryTool-SearchResult-bfe1e0f5/828.webp 828w, /generated/SearchQueryTool-SearchResult-bfe1e0f5/960.webp 960w, /generated/SearchQueryTool-SearchResult-bfe1e0f5/1018.webp 1018w&quot; sizes=&quot;(min-width: 1018px) 1018px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;SearchQueryTool: SearchResult&quot; src=&quot;/generated/SearchQueryTool-SearchResult-bfe1e0f5/1018.png&quot; srcset=&quot;/generated/SearchQueryTool-SearchResult-bfe1e0f5/320.png 320w, /generated/SearchQueryTool-SearchResult-bfe1e0f5/480.png 480w, /generated/SearchQueryTool-SearchResult-bfe1e0f5/640.png 640w, /generated/SearchQueryTool-SearchResult-bfe1e0f5/750.png 750w, /generated/SearchQueryTool-SearchResult-bfe1e0f5/828.png 828w, /generated/SearchQueryTool-SearchResult-bfe1e0f5/960.png 960w, /generated/SearchQueryTool-SearchResult-bfe1e0f5/1018.png 1018w&quot; sizes=&quot;(min-width: 1018px) 1018px, 100vw&quot; width=&quot;1018&quot; height=&quot;428&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h1 id=&quot;final-notes&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;final notes&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#final-notes&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Final Notes&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;The function uses PnP.Core Authentication to connect to MS Graph and a SharePoint “Proxy” Add-In with AppOnly Permissions to write to the SharePoint User Profile Service:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/GraphSyncArchitecture-bfe1e0f5/320.webp 320w, /generated/GraphSyncArchitecture-bfe1e0f5/480.webp 480w, /generated/GraphSyncArchitecture-bfe1e0f5/640.webp 640w, /generated/GraphSyncArchitecture-bfe1e0f5/750.webp 750w, /generated/GraphSyncArchitecture-bfe1e0f5/828.webp 828w, /generated/GraphSyncArchitecture-bfe1e0f5/960.webp 960w, /generated/GraphSyncArchitecture-bfe1e0f5/1245.webp 1245w&quot; sizes=&quot;(min-width: 1245px) 1245px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;MS Graph - UPA Sync Architecture&quot; src=&quot;/generated/GraphSyncArchitecture-bfe1e0f5/1245.jpeg&quot; srcset=&quot;/generated/GraphSyncArchitecture-bfe1e0f5/320.jpeg 320w, /generated/GraphSyncArchitecture-bfe1e0f5/480.jpeg 480w, /generated/GraphSyncArchitecture-bfe1e0f5/640.jpeg 640w, /generated/GraphSyncArchitecture-bfe1e0f5/750.jpeg 750w, /generated/GraphSyncArchitecture-bfe1e0f5/828.jpeg 828w, /generated/GraphSyncArchitecture-bfe1e0f5/960.jpeg 960w, /generated/GraphSyncArchitecture-bfe1e0f5/1245.jpeg 1245w&quot; sizes=&quot;(min-width: 1245px) 1245px, 100vw&quot; width=&quot;1245&quot; height=&quot;803&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;And Kudos to &lt;a href=&quot;https://dariuspintilie.eu/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Darius&lt;/a&gt; for figuring that out in one of our customer projects 👍🦄&lt;/li&gt;
&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title type="html">Troubleshooting SharePoint Online Search</title>
    <link href="https://blog.loitzl.com/posts/troubleshooting-sharepoint-online-search" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/troubleshooting-sharepoint-online-search</id>
    <updated>2021-11-27T23:40:32.169Z</updated>
    <summary type="html">Troubleshooting search in SharePoint Online can be hard. This article elaborates all reverse engineering means I know of.</summary>
    <content type="html">&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/Teaser-Picture-322f944b/320.webp 320w, /generated/Teaser-Picture-322f944b/480.webp 480w, /generated/Teaser-Picture-322f944b/640.webp 640w, /generated/Teaser-Picture-322f944b/750.webp 750w, /generated/Teaser-Picture-322f944b/828.webp 828w, /generated/Teaser-Picture-322f944b/960.webp 960w, /generated/Teaser-Picture-322f944b/1006.webp 1006w&quot; sizes=&quot;(min-width: 1006px) 1006px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Search Result with Managed Property&quot; src=&quot;/generated/Teaser-Picture-322f944b/1006.png&quot; srcset=&quot;/generated/Teaser-Picture-322f944b/320.png 320w, /generated/Teaser-Picture-322f944b/480.png 480w, /generated/Teaser-Picture-322f944b/640.png 640w, /generated/Teaser-Picture-322f944b/750.png 750w, /generated/Teaser-Picture-322f944b/828.png 828w, /generated/Teaser-Picture-322f944b/960.png 960w, /generated/Teaser-Picture-322f944b/1006.png 1006w&quot; sizes=&quot;(min-width: 1006px) 1006px, 100vw&quot; width=&quot;1006&quot; height=&quot;355&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h1 id=&quot;introduction&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;introduction&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#introduction&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Lately I had the chance to troubleshoot an issue we had with SharePoint Online Search. This article summarizes what I have learned with a small example scenario.&lt;/p&gt;
&lt;p&gt;First lets add some site columns&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;one simple Text column &lt;code&gt;SampleTextProperty1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;and a managed metadata column &lt;code&gt;SampleTaxonomyProperty1&lt;/code&gt; to make it more intesting&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/SiteColumns-322f944b/320.webp 320w, /generated/SiteColumns-322f944b/480.webp 480w, /generated/SiteColumns-322f944b/640.webp 640w, /generated/SiteColumns-322f944b/750.webp 750w, /generated/SiteColumns-322f944b/828.webp 828w, /generated/SiteColumns-322f944b/960.webp 960w, /generated/SiteColumns-322f944b/1253.webp 1253w&quot; sizes=&quot;(min-width: 1253px) 1253px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Create Site Columns&quot; src=&quot;/generated/SiteColumns-322f944b/1253.png&quot; srcset=&quot;/generated/SiteColumns-322f944b/320.png 320w, /generated/SiteColumns-322f944b/480.png 480w, /generated/SiteColumns-322f944b/640.png 640w, /generated/SiteColumns-322f944b/750.png 750w, /generated/SiteColumns-322f944b/828.png 828w, /generated/SiteColumns-322f944b/960.png 960w, /generated/SiteColumns-322f944b/1253.png 1253w&quot; sizes=&quot;(min-width: 1253px) 1253px, 100vw&quot; width=&quot;1253&quot; height=&quot;362&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Then add the site columns to a document library:&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/AddSiteColumnsToDocLib-322f944b/320.webp 320w, /generated/AddSiteColumnsToDocLib-322f944b/480.webp 480w, /generated/AddSiteColumnsToDocLib-322f944b/640.webp 640w, /generated/AddSiteColumnsToDocLib-322f944b/750.webp 750w, /generated/AddSiteColumnsToDocLib-322f944b/828.webp 828w, /generated/AddSiteColumnsToDocLib-322f944b/960.webp 960w, /generated/AddSiteColumnsToDocLib-322f944b/1024.webp 1024w&quot; sizes=&quot;(min-width: 1024px) 1024px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Add Site Columns to Document Library&quot; src=&quot;/generated/AddSiteColumnsToDocLib-322f944b/1024.png&quot; srcset=&quot;/generated/AddSiteColumnsToDocLib-322f944b/320.png 320w, /generated/AddSiteColumnsToDocLib-322f944b/480.png 480w, /generated/AddSiteColumnsToDocLib-322f944b/640.png 640w, /generated/AddSiteColumnsToDocLib-322f944b/750.png 750w, /generated/AddSiteColumnsToDocLib-322f944b/828.png 828w, /generated/AddSiteColumnsToDocLib-322f944b/960.png 960w, /generated/AddSiteColumnsToDocLib-322f944b/1024.png 1024w&quot; sizes=&quot;(min-width: 1024px) 1024px, 100vw&quot; width=&quot;1024&quot; height=&quot;479&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Upload documents and set some metadata:&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/AddedSampleDocuments-322f944b/320.webp 320w, /generated/AddedSampleDocuments-322f944b/480.webp 480w, /generated/AddedSampleDocuments-322f944b/640.webp 640w, /generated/AddedSampleDocuments-322f944b/750.webp 750w, /generated/AddedSampleDocuments-322f944b/828.webp 828w, /generated/AddedSampleDocuments-322f944b/960.webp 960w, /generated/AddedSampleDocuments-322f944b/1224.webp 1224w&quot; sizes=&quot;(min-width: 1224px) 1224px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Add Sample Documents with metadata&quot; src=&quot;/generated/AddedSampleDocuments-322f944b/1224.png&quot; srcset=&quot;/generated/AddedSampleDocuments-322f944b/320.png 320w, /generated/AddedSampleDocuments-322f944b/480.png 480w, /generated/AddedSampleDocuments-322f944b/640.png 640w, /generated/AddedSampleDocuments-322f944b/750.png 750w, /generated/AddedSampleDocuments-322f944b/828.png 828w, /generated/AddedSampleDocuments-322f944b/960.png 960w, /generated/AddedSampleDocuments-322f944b/1224.png 1224w&quot; sizes=&quot;(min-width: 1224px) 1224px, 100vw&quot; width=&quot;1224&quot; height=&quot;388&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h2 id=&quot;analyze-crawl-log&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;analyze crawl log&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#analyze-crawl-log&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Analyze Crawl Log&lt;/h2&gt;
&lt;p&gt;We can immediately check if the documents get crawled with the &lt;a href=&quot;https://pnp.github.io/powershell/cmdlets/Get-PnPSearchCrawlLog.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Get-PnPSearchCrawlLog&lt;/code&gt;&lt;/a&gt; PnP Powershell Commandlet, the &lt;code&gt;-Filter&lt;/code&gt; parameter allows to filter by site url for example.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;$ &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Connect-PnPOnline&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Url https:&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;loitzl2.sharepoint.com&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;sites&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ManagedProperties&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;DeviceLogin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;$ &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Get-PnPSearchCrawlLog&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;   -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Filter https:&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;loitzl2.sharepoint.com&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;sites&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ManagedProperties&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Url             : https:&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;loitzl2.sharepoint.com&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;sites&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ManagedProperties&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Shared Documents&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Test Page.pdf&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;CrawlTime       : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;2021&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 6&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;25&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; AM&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ItemTime        : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;2021&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; PM&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;LogLevel        : Success&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Status          :&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ItemId          : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;58807014&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ContentSourceId : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Url             : https:&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;loitzl2.sharepoint.com&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;sites&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ManagedProperties&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Shared Documents&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Invoice.docx&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;CrawlTime       : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;2021&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 6&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;22&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;24&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; AM&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ItemTime        : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;12&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;2021&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;21&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;54&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; PM&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;LogLevel        : Success&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Status          :&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ItemId          : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;58807017&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ContentSourceId : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[..]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;✅ Seems to be OK&lt;/p&gt;
&lt;p&gt;The permissions for reading the search crawl log can be set in the SharePoint Admin Center:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/_layouts/15/searchadmin/crawllogreadpermission.aspx&lt;/code&gt;&lt;/p&gt;
&lt;h2 id=&quot;re-crawl-a-document-library&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;re crawl a document library&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#re-crawl-a-document-library&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Re-crawl a Document Library&lt;/h2&gt;
&lt;p&gt;In case we need to tell the search crawler to crawl the document library again the &lt;a href=&quot;https://pnp.github.io/powershell/cmdlets/Request-PnPReIndexList.html?q=Request-PnPReIndexList&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Request-PnPReIndexList&lt;/code&gt;&lt;/a&gt; pnp powershell commandlet can be used:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;$ &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Request-PnPReIndexList&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Identity &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;Documents&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same function is surfaced in the UI:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/sharepoint/crawl-site-content#re-index-a-document-library-or-a-list&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.microsoft.com/en-us/sharepoint/crawl-site-content&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;🤓 What happens behind the scenes ist, that the &lt;code&gt;vti_searchversion&lt;/code&gt; property bag value gets increased:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; reIndexKey &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;vti_searchversion&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; searchversion &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;list&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;PropertyBagContainsKey&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;reIndexKey&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  searchversion&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;list&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;GetPropertyBagValueInt&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;reIndexKey&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;try&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  list&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;SetPropertyBagValue&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;reIndexKey&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;searchversion&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[...]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;see &lt;a href=&quot;https://github.com/pnp/pnpframework/blob/770d9bd03873358565773faa025f456d4a3a35fe/src/lib/PnP.Framework/Extensions/ListExtensions.cs#L2248&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Microsoft.SharePoint.Client.ListExtensions&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And, btw, the same works for whole sites with the &lt;a href=&quot;https://pnp.github.io/powershell/cmdlets/Request-PnPReIndexWeb.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Request-PnPReIndexWeb&lt;/code&gt;&lt;/a&gt; commandlet which writes &lt;code&gt;vti_searchversion&lt;/code&gt; to the &lt;code&gt;SP.Web&lt;/code&gt; property bag.&lt;/p&gt;
&lt;p&gt;see &lt;a href=&quot;https://github.com/pnp/pnpframework/blob/770d9bd03873358565773faa025f456d4a3a35fe/src/lib/PnP.Framework/Extensions/WebExtensions.cs#L1003&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Microsoft.SharePoint.Client.WebExtensions&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&quot;managed-properties&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;managed properties&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#managed-properties&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Managed Properties&lt;/h1&gt;
&lt;p&gt;After giving the search crawler some time, two new managed properties will probably show up:&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/Sample-ManagedProperties-322f944b/320.webp 320w, /generated/Sample-ManagedProperties-322f944b/480.webp 480w, /generated/Sample-ManagedProperties-322f944b/493.webp 493w&quot; sizes=&quot;(min-width: 493px) 493px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Sample Managed Properties&quot; src=&quot;/generated/Sample-ManagedProperties-322f944b/493.png&quot; srcset=&quot;/generated/Sample-ManagedProperties-322f944b/320.png 320w, /generated/Sample-ManagedProperties-322f944b/480.png 480w, /generated/Sample-ManagedProperties-322f944b/493.png 493w&quot; sizes=&quot;(min-width: 493px) 493px, 100vw&quot; width=&quot;493&quot; height=&quot;348&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Using the &lt;a href=&quot;https://pnp.github.io/powershell/cmdlets/Submit-PnPSearchQuery.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Submit-PnPSearchQuery&lt;/code&gt;&lt;/a&gt; search results can be retrieved:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;$ &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Submit-PnPSearchQuery&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;     -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Query &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;SampleTextProperty1OWSTEXT:&apos;An Invoice&apos;&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;GroupTemplateId              : &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ItemTemplateId               : &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Properties                   : {[&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;RenderTemplateId&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; ~&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;sitecollection&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;catalogs&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;masterpage&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;Display&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; Templates&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;Sea&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;                               rch&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;Group&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;Default.js&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;QueryModification&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; SampleTextProperty1OWSTEXT&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&apos;An Invo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                               ice&apos;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;ContentClass&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;urn&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;SPSPeople&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;ExecutionTimeMs&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;StartR&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;                               ecord&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]…}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;QueryId                      : 0fc5abbe&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;875a&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;2e7c&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;32dc&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;e49b00dcfb21&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;QueryRuleId                  : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;00000000&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0000&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0000&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0000&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;000000000000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ResultRows                   : {System.Collections.Generic.Dictionary&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;System.String&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;System.Object&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ResultTitle                  : &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ResultTitleUrl               : &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;RowCount                     : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;TableType                    : RelevantResults&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;TotalRows                    : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;TotalRowsIncludingDuplicates : &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;TypeId                       : {6780df59&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1036&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;4912&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;829b&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;432354f22656}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We receive exactly the one item in the document library.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;$ (&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Submit-PnPSearchQuery&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Query &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;SampleTextProperty1OWSTEXT:&apos;An Invoice&apos;&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;     .ResultRows &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;       .OriginalPath&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;https:&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;//&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ManagedProperties&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Shared Documents&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Invoice.docx&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can also retrieve the value of the Managed Property &lt;code&gt;SampleTextProperty1OWSTEXT&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;$ (&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Submit-PnPSearchQuery&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Query &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;SampleTextProperty1OWSTEXT:&apos;A printer test page&apos;&quot;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;SelectProperties SampleTextProperty1OWSTEXT) &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;     .ResultRows &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;        .SampleTextProperty1OWSTEXT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;A printer test page&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One problem that arises here that the other managed property &lt;code&gt;owstaxIdSampleTaxonomyProperty11&lt;/code&gt; contains the ids of the taxonomy tree.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;$ (&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Submit-PnPSearchQuery&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;     -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Query &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;SampleTextProperty1OWSTEXT:&apos;A printer test page&apos;&quot;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;     -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;SelectProperties owstaxIdSampleTaxonomyProperty11) &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;        .ResultRows &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;           .owstaxIdSampleTaxonomyProperty11        &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;GP0&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;#318e3a7f-0f62-4d57-bf0e-e8b3d693ba6e;L0|#0318e3a7f-0f62-4d57-bf0e-e8b3d693ba6e|R＆D;GTSet|#8ed8c9ea-7052-4c1d-a4d7-b9c10bffea6f&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Search also creates a crawled property containing the label of a taxonomy field:&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/Sample-CrawledProperties-322f944b/320.webp 320w, /generated/Sample-CrawledProperties-322f944b/480.webp 480w, /generated/Sample-CrawledProperties-322f944b/565.webp 565w&quot; sizes=&quot;(min-width: 565px) 565px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Sample Crawled Properties&quot; src=&quot;/generated/Sample-CrawledProperties-322f944b/565.png&quot; srcset=&quot;/generated/Sample-CrawledProperties-322f944b/320.png 320w, /generated/Sample-CrawledProperties-322f944b/480.png 480w, /generated/Sample-CrawledProperties-322f944b/565.png 565w&quot; sizes=&quot;(min-width: 565px) 565px, 100vw&quot; width=&quot;565&quot; height=&quot;409&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;So lets create a new managed property named &lt;code&gt;SampleTaxonomyProperty1&lt;/code&gt; and map the crawled property &lt;code&gt;ows_SampleTaxonomyProperty11&lt;/code&gt; to it:&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/Mapped-CrawledProperty-322f944b/320.webp 320w, /generated/Mapped-CrawledProperty-322f944b/480.webp 480w, /generated/Mapped-CrawledProperty-322f944b/640.webp 640w, /generated/Mapped-CrawledProperty-322f944b/750.webp 750w, /generated/Mapped-CrawledProperty-322f944b/828.webp 828w, /generated/Mapped-CrawledProperty-322f944b/960.webp 960w, /generated/Mapped-CrawledProperty-322f944b/1268.webp 1268w&quot; sizes=&quot;(min-width: 1268px) 1268px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Mapped-CrawledProperty&quot; src=&quot;/generated/Mapped-CrawledProperty-322f944b/1268.png&quot; srcset=&quot;/generated/Mapped-CrawledProperty-322f944b/320.png 320w, /generated/Mapped-CrawledProperty-322f944b/480.png 480w, /generated/Mapped-CrawledProperty-322f944b/640.png 640w, /generated/Mapped-CrawledProperty-322f944b/750.png 750w, /generated/Mapped-CrawledProperty-322f944b/828.png 828w, /generated/Mapped-CrawledProperty-322f944b/960.png 960w, /generated/Mapped-CrawledProperty-322f944b/1268.png 1268w&quot; sizes=&quot;(min-width: 1268px) 1268px, 100vw&quot; width=&quot;1268&quot; height=&quot;175&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;And retrieve it:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;$ (&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Submit-PnPSearchQuery&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; ``&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;   -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Query &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;SampleTextProperty1OWSTEXT:&apos;A printer test page&apos;&quot;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;   -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;SelectProperties SampleTaxonomyProperty1) &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;     .ResultRows &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;       .SampleTaxonomyProperty1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;R&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; D&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Thats a lot more readable ✌️&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; Might take a couple of minutes after mapping for the value to show up.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h1 id=&quot;search-query-tool&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;search query tool&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#search-query-tool&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Search Query Tool&lt;/h1&gt;
&lt;p&gt;Another nice tool is the &lt;a href=&quot;https://github.com/pnp/PnP-Tools/tree/master/Solutions/SharePoint.Search.QueryTool&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SharePoint Search Query Tool&lt;/a&gt; which has been archived in the PnP github repo.
It allows doing the same things as with &lt;a href=&quot;https://pnp.github.io/powershell/cmdlets/Submit-PnPSearchQuery.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Submit-PnPSearchQuery&lt;/code&gt;&lt;/a&gt;, especially getting all managed properties can be helpful:&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/List-AllManagedProperties-322f944b/320.webp 320w, /generated/List-AllManagedProperties-322f944b/480.webp 480w, /generated/List-AllManagedProperties-322f944b/640.webp 640w, /generated/List-AllManagedProperties-322f944b/750.webp 750w, /generated/List-AllManagedProperties-322f944b/828.webp 828w, /generated/List-AllManagedProperties-322f944b/960.webp 960w, /generated/List-AllManagedProperties-322f944b/1489.webp 1489w&quot; sizes=&quot;(min-width: 1489px) 1489px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;List All ManagedProperties&quot; src=&quot;/generated/List-AllManagedProperties-322f944b/1489.png&quot; srcset=&quot;/generated/List-AllManagedProperties-322f944b/320.png 320w, /generated/List-AllManagedProperties-322f944b/480.png 480w, /generated/List-AllManagedProperties-322f944b/640.png 640w, /generated/List-AllManagedProperties-322f944b/750.png 750w, /generated/List-AllManagedProperties-322f944b/828.png 828w, /generated/List-AllManagedProperties-322f944b/960.png 960w, /generated/List-AllManagedProperties-322f944b/1489.png 1489w&quot; sizes=&quot;(min-width: 1489px) 1489px, 100vw&quot; width=&quot;1489&quot; height=&quot;1077&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;There is also a possibility to retrieve (at least the names of) all crawled properties of the item:&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/List-AllCrawledPropertyNames-322f944b/320.webp 320w, /generated/List-AllCrawledPropertyNames-322f944b/480.webp 480w, /generated/List-AllCrawledPropertyNames-322f944b/640.webp 640w, /generated/List-AllCrawledPropertyNames-322f944b/750.webp 750w, /generated/List-AllCrawledPropertyNames-322f944b/828.webp 828w, /generated/List-AllCrawledPropertyNames-322f944b/960.webp 960w, /generated/List-AllCrawledPropertyNames-322f944b/1507.webp 1507w&quot; sizes=&quot;(min-width: 1507px) 1507px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;List All Crawled Property Names&quot; src=&quot;/generated/List-AllCrawledPropertyNames-322f944b/1507.png&quot; srcset=&quot;/generated/List-AllCrawledPropertyNames-322f944b/320.png 320w, /generated/List-AllCrawledPropertyNames-322f944b/480.png 480w, /generated/List-AllCrawledPropertyNames-322f944b/640.png 640w, /generated/List-AllCrawledPropertyNames-322f944b/750.png 750w, /generated/List-AllCrawledPropertyNames-322f944b/828.png 828w, /generated/List-AllCrawledPropertyNames-322f944b/960.png 960w, /generated/List-AllCrawledPropertyNames-322f944b/1507.png 1507w&quot; sizes=&quot;(min-width: 1507px) 1507px, 100vw&quot; width=&quot;1507&quot; height=&quot;984&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h1 id=&quot;conclusion&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;conclusion&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#conclusion&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Working with Search in SharePoint Online with a SharePoint on-prem background feels odd at the beginning since its easy to just access the ULS Logs.&lt;/p&gt;
&lt;p&gt;Actually there are a plenty of possbilities around to analyze Managed Properties, Crawled Properties and the Crawl Log itself.&lt;/p&gt;
&lt;p&gt;I will update that article if I find some new tricks.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;💙&lt;/p&gt;
&lt;/blockquote&gt;</content>
  </entry>
  <entry>
    <title type="html">Creating SharePoint Terms using the App Context with the new PnP Core SDK</title>
    <link href="https://blog.loitzl.com/posts/creating-sharePoint-managed-metadata-terms-using-the-new-pnp-core-sdk" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/creating-sharePoint-managed-metadata-terms-using-the-new-pnp-core-sdk</id>
    <updated>2021-05-23T23:40:32.169Z</updated>
    <summary type="html">Working with the new PnP Core SDK is quite straight forward. Creating terms in the context of an App is tricky... as it ever was.</summary>
    <content type="html">&lt;p&gt;&lt;img alt=&quot;Logo&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;321&quot; height=&quot;140&quot; src=&quot;/_astro/logo.CmFiv0WG_VpKLY.svg&quot;&gt;&lt;/p&gt;
&lt;h1 id=&quot;introduction&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;introduction&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#introduction&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Introduction&lt;/h1&gt;
&lt;p&gt;Lately I had the chance to work with the new &lt;a href=&quot;https://pnp.github.io/pnpcore/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PnP Core SDK&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Its running under dot net core, which is an awesome improvement compared to the older &lt;a href=&quot;https://github.com/pnp/PnP-Sites-Core&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PnP Sites Core&lt;/a&gt; which I used a lot in the past couple of years ❤️&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/PnP-Core-GA-d4ac7407/320.webp 320w, /generated/PnP-Core-GA-d4ac7407/480.webp 480w, /generated/PnP-Core-GA-d4ac7407/574.webp 574w&quot; sizes=&quot;(min-width: 574px) 574px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;PnP Core SDK general availability&quot; src=&quot;/generated/PnP-Core-GA-d4ac7407/574.png&quot; srcset=&quot;/generated/PnP-Core-GA-d4ac7407/320.png 320w, /generated/PnP-Core-GA-d4ac7407/480.png 480w, /generated/PnP-Core-GA-d4ac7407/574.png 574w&quot; sizes=&quot;(min-width: 574px) 574px, 100vw&quot; width=&quot;574&quot; height=&quot;440&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;The methods for accessing the termstore leverage the &lt;a href=&quot;https://docs.microsoft.com/en-us/graph/api/termstore-term-post?view=graph-rest-beta&amp;#x26;tabs=http&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;new taxonomy endpoint&lt;/a&gt; of MS Graph beta endpoint.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/TermStore-Graph-Endpoint-d4ac7407/320.webp 320w, /generated/TermStore-Graph-Endpoint-d4ac7407/480.webp 480w, /generated/TermStore-Graph-Endpoint-d4ac7407/640.webp 640w, /generated/TermStore-Graph-Endpoint-d4ac7407/750.webp 750w, /generated/TermStore-Graph-Endpoint-d4ac7407/828.webp 828w, /generated/TermStore-Graph-Endpoint-d4ac7407/960.webp 960w, /generated/TermStore-Graph-Endpoint-d4ac7407/1267.webp 1267w&quot; sizes=&quot;(min-width: 1267px) 1267px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;MS Graph TermStore&quot; src=&quot;/generated/TermStore-Graph-Endpoint-d4ac7407/1267.png&quot; srcset=&quot;/generated/TermStore-Graph-Endpoint-d4ac7407/320.png 320w, /generated/TermStore-Graph-Endpoint-d4ac7407/480.png 480w, /generated/TermStore-Graph-Endpoint-d4ac7407/640.png 640w, /generated/TermStore-Graph-Endpoint-d4ac7407/750.png 750w, /generated/TermStore-Graph-Endpoint-d4ac7407/828.png 828w, /generated/TermStore-Graph-Endpoint-d4ac7407/960.png 960w, /generated/TermStore-Graph-Endpoint-d4ac7407/1267.png 1267w&quot; sizes=&quot;(min-width: 1267px) 1267px, 100vw&quot; width=&quot;1267&quot; height=&quot;548&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;The article shows&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the setup of an Azure AD App using the PnP Powershell Module and&lt;/li&gt;
&lt;li&gt;an Azure Function accessing the Term Store using client certificate authentication.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;setup-authentication&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;setup authentication&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#setup-authentication&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Setup Authentication&lt;/h1&gt;
&lt;p&gt;Setting up the Azure AD App for this is straight forward using the &lt;a href=&quot;https://pnp.github.io/powershell/cmdlets/Register-PnPAzureADApp.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Register-PnPAzureADApp&lt;/code&gt;&lt;/a&gt; PowerShell commandlet.&lt;/p&gt;
&lt;p&gt;Im am doing this with macOS Big Sur, so first we have to &lt;a href=&quot;https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-macos?view=powershell-7.1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;install PowerShell&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; brew&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --cask&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; powershell&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/Powershell-Install-Mac-d4ac7407/320.webp 320w, /generated/Powershell-Install-Mac-d4ac7407/480.webp 480w, /generated/Powershell-Install-Mac-d4ac7407/640.webp 640w, /generated/Powershell-Install-Mac-d4ac7407/750.webp 750w, /generated/Powershell-Install-Mac-d4ac7407/828.webp 828w, /generated/Powershell-Install-Mac-d4ac7407/960.webp 960w, /generated/Powershell-Install-Mac-d4ac7407/1362.webp 1362w&quot; sizes=&quot;(min-width: 1362px) 1362px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;PowerShell Install Mac&quot; src=&quot;/generated/Powershell-Install-Mac-d4ac7407/1362.png&quot; srcset=&quot;/generated/Powershell-Install-Mac-d4ac7407/320.png 320w, /generated/Powershell-Install-Mac-d4ac7407/480.png 480w, /generated/Powershell-Install-Mac-d4ac7407/640.png 640w, /generated/Powershell-Install-Mac-d4ac7407/750.png 750w, /generated/Powershell-Install-Mac-d4ac7407/828.png 828w, /generated/Powershell-Install-Mac-d4ac7407/960.png 960w, /generated/Powershell-Install-Mac-d4ac7407/1362.png 1362w&quot; sizes=&quot;(min-width: 1362px) 1362px, 100vw&quot; width=&quot;1362&quot; height=&quot;380&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;That seemed to work, no lets start PowerShell.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; pwsh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Install the &lt;a href=&quot;https://pnp.github.io/powershell/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;PnP PowerShell Module&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Install-Module&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Name &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;PnP.PowerShell&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Untrusted repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;You are installing the modules &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; an untrusted repository. &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;If&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; you trust this repository&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; change its InstallationPolicy value by running the &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Set-PSRepository&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; cmdlet. Are you sure you want to install the modules &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &apos;PSGallery&apos;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;Y&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;] Yes  [&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;A&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;] Yes to All  [&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;] No  [&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;L&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;] No to All  [&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;S&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;] Suspend  [&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;] Help (&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; is &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;N&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;): y&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The App can be created and trusted in Azure Active Directory using the &lt;code&gt;Register-PnPAzureADApp&lt;/code&gt; PnP commandlet. This commandlet can also create a self-signed certificate out of the box, but this only works on Windows machines.&lt;/p&gt;
&lt;p&gt;On Linux/Mac based system we can provide our own certificate using the following &lt;code&gt;openssl&lt;/code&gt; commands:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# Create the certificate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# Convert to pfx file&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ openssl pkcs12 -export -out certificate.pfx -inkey key.pem -in cert.pem&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The command in line 4 converts the certificate created in line 2 to a pfx file, which should have a password.&lt;/p&gt;
&lt;p&gt;Now the Client Application can be registered using the &lt;a href=&quot;https://pnp.github.io/powershell/cmdlets/Register-PnPAzureADApp.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;Register-PnPAzureADApp&lt;/code&gt;&lt;/a&gt; command.
The password used for creating the pfx file has now to be passed as the &lt;code&gt;CertificatePassword&lt;/code&gt; (line 5) parameter.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;-Scopes&lt;/code&gt; parameter in line 8 is requesting the necessary permissions.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Register-PnPAzureADApp `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  -ApplicationName TestApp1 `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  -Tenant &amp;#x3C;tenant&gt;.onmicrosoft.com ` &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  -CertificatePath certificate.pfx `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  -CertificatePassword (ConvertTo-SecureString -String &quot;&amp;#x3C;cert password&gt;&quot; -AsPlainText -Force) `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  -Username &quot;&amp;#x3C;user&gt;@&amp;#x3C;tenant&gt;.onmicrosoft.com&quot; `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  -Password (ConvertTo-SecureString -String &quot;&amp;#x3C;password&gt;&quot; -AsPlainText -Force) `&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  -Scopes &quot;SPO.TermStore.ReadWrite.All&quot;, &quot;MSGraph.TermStore.ReadWrite.All&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On Windows systems the consent window will open automatically. On Linux/Mac based systems the consent Url is written to STDOUT and should be pasted into a browser window.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;https://login.microsoftonline.com&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;      /loitzl.onmicrosoft.com/v2.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;        /adminconsent&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    ?client_id&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;=791ff0ac-1f93-47fc-8629-6b20f360036f&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;scope&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;https://graph.microsoft.com/.default&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;redirect_uri&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;http://localhost&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/Admin-Consent-d4ac7407/320.webp 320w, /generated/Admin-Consent-d4ac7407/480.webp 480w, /generated/Admin-Consent-d4ac7407/640.webp 640w, /generated/Admin-Consent-d4ac7407/750.webp 750w, /generated/Admin-Consent-d4ac7407/828.webp 828w, /generated/Admin-Consent-d4ac7407/960.webp 960w, /generated/Admin-Consent-d4ac7407/1464.webp 1464w&quot; sizes=&quot;(min-width: 1464px) 1464px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Admin Consent&quot; src=&quot;/generated/Admin-Consent-d4ac7407/1464.png&quot; srcset=&quot;/generated/Admin-Consent-d4ac7407/320.png 320w, /generated/Admin-Consent-d4ac7407/480.png 480w, /generated/Admin-Consent-d4ac7407/640.png 640w, /generated/Admin-Consent-d4ac7407/750.png 750w, /generated/Admin-Consent-d4ac7407/828.png 828w, /generated/Admin-Consent-d4ac7407/960.png 960w, /generated/Admin-Consent-d4ac7407/1464.png 1464w&quot; sizes=&quot;(min-width: 1464px) 1464px, 100vw&quot; width=&quot;1464&quot; height=&quot;1454&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;The return value contains the necessary values for authentication:&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/Register-PnPAzureADApp-result-d4ac7407/320.webp 320w, /generated/Register-PnPAzureADApp-result-d4ac7407/480.webp 480w, /generated/Register-PnPAzureADApp-result-d4ac7407/640.webp 640w, /generated/Register-PnPAzureADApp-result-d4ac7407/750.webp 750w, /generated/Register-PnPAzureADApp-result-d4ac7407/828.webp 828w, /generated/Register-PnPAzureADApp-result-d4ac7407/960.webp 960w, /generated/Register-PnPAzureADApp-result-d4ac7407/1096.webp 1096w&quot; sizes=&quot;(min-width: 1096px) 1096px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Register-PnPAzureADApp Result&quot; src=&quot;/generated/Register-PnPAzureADApp-result-d4ac7407/1096.png&quot; srcset=&quot;/generated/Register-PnPAzureADApp-result-d4ac7407/320.png 320w, /generated/Register-PnPAzureADApp-result-d4ac7407/480.png 480w, /generated/Register-PnPAzureADApp-result-d4ac7407/640.png 640w, /generated/Register-PnPAzureADApp-result-d4ac7407/750.png 750w, /generated/Register-PnPAzureADApp-result-d4ac7407/828.png 828w, /generated/Register-PnPAzureADApp-result-d4ac7407/960.png 960w, /generated/Register-PnPAzureADApp-result-d4ac7407/1096.png 1096w&quot; sizes=&quot;(min-width: 1096px) 1096px, 100vw&quot; width=&quot;1096&quot; height=&quot;318&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The certificate.pfx file has been renamed to &amp;#x3C;AppName&gt;.pfx and &amp;#x3C;AppName&gt;.cer (here: TestApp1)&lt;/li&gt;
&lt;li&gt;The AzureAppId/ClientId of the newly created application&lt;/li&gt;
&lt;li&gt;The Certificate Thumbprint&lt;/li&gt;
&lt;li&gt;And the Base64 Encoded certificate data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This data is needed for configuring the Azure Function authentication.&lt;/p&gt;
&lt;h1 id=&quot;the-function&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;the function&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#the-function&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Function&lt;/h1&gt;
&lt;p&gt;After creating a new function project and adding the PnP Core SDK package with&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; dotnet&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; add&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; package&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; PnP.Core&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --version&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 1.1.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;adjust the &lt;code&gt;local.settings.json&lt;/code&gt; file with the values of the result from &lt;code&gt;Register-PnPAzureADApp&lt;/code&gt; result above:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SiteUrl: Url to connect to&lt;/li&gt;
&lt;li&gt;TenantId: can be retrieved with &lt;code&gt;Get-PnPTenantId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ClientId: the AzureAppId/ClientId from &lt;code&gt;Register-PnPAzureADApp&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;CertificateThumbPrint: also from &lt;code&gt;Register-PnPAzureADApp&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/local.settings.json-d4ac7407/320.webp 320w, /generated/local.settings.json-d4ac7407/480.webp 480w, /generated/local.settings.json-d4ac7407/640.webp 640w, /generated/local.settings.json-d4ac7407/750.webp 750w, /generated/local.settings.json-d4ac7407/828.webp 828w, /generated/local.settings.json-d4ac7407/960.webp 960w, /generated/local.settings.json-d4ac7407/1142.webp 1142w&quot; sizes=&quot;(min-width: 1142px) 1142px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;local settings json&quot; src=&quot;/generated/local.settings.json-d4ac7407/1142.png&quot; srcset=&quot;/generated/local.settings.json-d4ac7407/320.png 320w, /generated/local.settings.json-d4ac7407/480.png 480w, /generated/local.settings.json-d4ac7407/640.png 640w, /generated/local.settings.json-d4ac7407/750.png 750w, /generated/local.settings.json-d4ac7407/828.png 828w, /generated/local.settings.json-d4ac7407/960.png 960w, /generated/local.settings.json-d4ac7407/1142.png 1142w&quot; sizes=&quot;(min-width: 1142px) 1142px, 100vw&quot; width=&quot;1142&quot; height=&quot;360&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;In order to use the PnP Core SDK using dependency injection create a &lt;code&gt;Startup&lt;/code&gt; class inheriting from &lt;code&gt;FunctionsStartup&lt;/code&gt; as described in the &lt;a href=&quot;https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MSDN Docs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The full source code can be found &lt;a href=&quot;https://github.com/mloitzl/azurefunctionpnpcore&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;on my Github&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;public class Startup : FunctionsStartup&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    public override void Configure(IFunctionsHostBuilder builder)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        var config = builder.GetContext().Configuration;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        var settings = new Settings();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        config.Bind(settings);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        builder.Services.AddPnPCore(options =&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            options.DisableTelemetry = true;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            var authProvider = new X509CertificateAuthenticationProvider(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                settings.ClientId.ToString(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                settings.TenantId.ToString(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                StoreName.My,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                StoreLocation.CurrentUser,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                settings.CertificateThumbprint);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            options.DefaultAuthenticationProvider = authProvider;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;            options.Sites.Add(&quot;Default&quot;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                   new PnPCoreSiteOptions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                   {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                       SiteUrl = settings.SiteUrl.ToString(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                       AuthenticationProvider = authProvider&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                   });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In lines 10-17 client certificate authentication gets configured, a &lt;code&gt;Default&lt;/code&gt; connection is added with the &lt;code&gt;SiteUrl&lt;/code&gt;configured in the &lt;code&gt;local.settings.json&lt;/code&gt; in line 18 to 23.&lt;/p&gt;
&lt;p&gt;This allows us to use constructor injection to retrieve a &lt;code&gt;IPnPContextFactory&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; CreateTerm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;  private&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; IPnPContextFactory&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; _pnpContextFactory;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;  public&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; CreateTerm&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IPnPContextFactory&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; pnpContextFactory)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    _pnpContextFactory&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; pnpContextFactory&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;IPnPContextFactory&lt;/code&gt; can now be used to create a &lt;code&gt;PnPContext&lt;/code&gt; instance, retrieve the first &lt;code&gt;ITermGroup&lt;/code&gt; and first &lt;code&gt;ITermSet&lt;/code&gt; for simplicity (use the &lt;code&gt;*ById()&lt;/code&gt; methods in real life).&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;ITermSet&lt;/code&gt; we then create a new Term with &lt;code&gt;termSet.Terms.AddAsync(name)&lt;/code&gt; method (line 8).&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;using (var pnpContext = await _pnpContextFactory.CreateAsync(&quot;Default&quot;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    _logger.LogInformation(&quot;Creating Term &apos;{DefaultLabel}&apos;&quot;, name);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    try&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        var termGroup = pnpContext.TermStore.Groups.First();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        var termSet = termGroup.Sets.First();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        var newTerm = await termSet.Terms.AddAsync(name);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        return new OkObjectResult(new { id = newTerm.Id });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    catch (MicrosoftGraphServiceException ex)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        _logger.LogError((Exception)ex, ex.Error.ToString());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;        return new BadRequestObjectResult(ex.Error);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After starting the function in debug mode with F5, we see, that this does not work actually.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/Terminal-Functionhost-d4ac7407/320.webp 320w, /generated/Terminal-Functionhost-d4ac7407/480.webp 480w, /generated/Terminal-Functionhost-d4ac7407/640.webp 640w, /generated/Terminal-Functionhost-d4ac7407/750.webp 750w, /generated/Terminal-Functionhost-d4ac7407/828.webp 828w, /generated/Terminal-Functionhost-d4ac7407/960.webp 960w, /generated/Terminal-Functionhost-d4ac7407/1274.webp 1274w&quot; sizes=&quot;(min-width: 1274px) 1274px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;/generated/Terminal-Functionhost-d4ac7407/1274.png&quot; srcset=&quot;/generated/Terminal-Functionhost-d4ac7407/320.png 320w, /generated/Terminal-Functionhost-d4ac7407/480.png 480w, /generated/Terminal-Functionhost-d4ac7407/640.png 640w, /generated/Terminal-Functionhost-d4ac7407/750.png 750w, /generated/Terminal-Functionhost-d4ac7407/828.png 828w, /generated/Terminal-Functionhost-d4ac7407/960.png 960w, /generated/Terminal-Functionhost-d4ac7407/1274.png 1274w&quot; sizes=&quot;(min-width: 1274px) 1274px, 100vw&quot; width=&quot;1274&quot; height=&quot;190&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;We get a &lt;a href=&quot;https://pnp.github.io/pnpcore/api/PnP.Core.MicrosoftGraphServiceException.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;MicrosoftGraphServiceException&lt;/code&gt;&lt;/a&gt; with the message&lt;/p&gt;
&lt;p&gt;❌  “The current user has insufficient permissions to perform this operation.”&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;HttpResponseCode:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 403&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Code:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; accessDenied&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Message:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; The&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; current&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; user&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; has&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; insufficient&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; permissions&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; to&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; perform&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; this&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; operation.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;ClientRequestId:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; a07d1a32-410f-4397-8157-e329310c7fb5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;date:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 2021-05-22T08:55:35&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;client-request-id:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; a07d1a32-410f-4397-8157-e329310c7fb5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;👉&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; PnP.Core:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Microsoft&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Graph&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; service&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; exception.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;the-problem&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;the problem&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#the-problem&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Problem&lt;/h1&gt;
&lt;p&gt;Accessing the SharePoint Termstore in the context of the Application (app-only context) needs an old trick that is still possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add the app principal “app@sharepoint” as Term Group Manager, and it works.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/Add-App-Principal-As-TermGroupManager-d4ac7407/320.webp 320w, /generated/Add-App-Principal-As-TermGroupManager-d4ac7407/480.webp 480w, /generated/Add-App-Principal-As-TermGroupManager-d4ac7407/640.webp 640w, /generated/Add-App-Principal-As-TermGroupManager-d4ac7407/750.webp 750w, /generated/Add-App-Principal-As-TermGroupManager-d4ac7407/828.webp 828w, /generated/Add-App-Principal-As-TermGroupManager-d4ac7407/960.webp 960w, /generated/Add-App-Principal-As-TermGroupManager-d4ac7407/1007.webp 1007w&quot; sizes=&quot;(min-width: 1007px) 1007px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Add App Principal As TermGroupManager&quot; src=&quot;/generated/Add-App-Principal-As-TermGroupManager-d4ac7407/1007.png&quot; srcset=&quot;/generated/Add-App-Principal-As-TermGroupManager-d4ac7407/320.png 320w, /generated/Add-App-Principal-As-TermGroupManager-d4ac7407/480.png 480w, /generated/Add-App-Principal-As-TermGroupManager-d4ac7407/640.png 640w, /generated/Add-App-Principal-As-TermGroupManager-d4ac7407/750.png 750w, /generated/Add-App-Principal-As-TermGroupManager-d4ac7407/828.png 828w, /generated/Add-App-Principal-As-TermGroupManager-d4ac7407/960.png 960w, /generated/Add-App-Principal-As-TermGroupManager-d4ac7407/1007.png 1007w&quot; sizes=&quot;(min-width: 1007px) 1007px, 100vw&quot; width=&quot;1007&quot; height=&quot;186&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;A google search with &lt;a href=&quot;https://www.google.com/search?q=i%3A0i.t%7C00000003-0000-0ff1-ce00-000000000000%7Capp%40sharepoint&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;“i:0i.t|00000003-0000-0ff1-ce00-000000000000|app@sharepoint”&lt;/a&gt; reveals, that there are sometimes problems with this approach but that it seems that it is widely used.&lt;/p&gt;
&lt;p&gt;Good troubleshoting tips can be found in the &lt;a href=&quot;https://github.com/SharePoint/sp-dev-docs/issues/6155&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Github issue’s discussion&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;conclusion&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;conclusion&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#conclusion&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;By the way, all this was created on a new Apple MacBook Pro M1. I really like the fact that more and more of the M365 developer and engineering workloads are now available cross-platform.&lt;/p&gt;
&lt;p&gt;Configuration the PnP Core SDK using the&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;cs&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AddPnPCore&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  this&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; IServiceCollection&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; services&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  Action&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;PnPCoreOptions&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; options&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;extension method and the integration into the &lt;a href=&quot;https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-5.0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;.net core dependency injection&lt;/a&gt; world is also a great feature.&lt;/p&gt;
&lt;h1 id=&quot;links&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;links&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#links&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Links&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Based on the sample Azure Function Code from &lt;a href=&quot;https://github.com/pnp/pnpcore/tree/dev/samples/Demo.AzureFunction&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Demo.AzureFunction&lt;/a&gt; in the PnP Core SDK github repo:&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;please see their &lt;a href=&quot;https://github.com/mloitzl/pnpcore/blob/dev/samples/Demo.AzureFunction/README.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Readme.MD&lt;/a&gt; for how to actually deploy it to Azure&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Certificates using &lt;a href=&quot;https://www.ssl.com/how-to/create-a-pfx-p12-certificate-file-using-openssl/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;openssl commandline&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.techmikael.com/2018/08/modifying-terms-using-app-only-tokens.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Modifying terms using app-only tokens in SharePoint – undocumented work-around&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The full source code can be found on &lt;a href=&quot;https://github.com/mloitzl/azurefunctionpnpcore&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;on Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title type="html">Setup mini Kubernetes Rancher K3S on Raspberry OS Lite</title>
    <link href="https://blog.loitzl.com/posts/setup-k3s-on-raspberryos-lite" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/setup-k3s-on-raspberryos-lite</id>
    <updated>2021-02-05T22:40:32.169Z</updated>
    <summary type="html">After finishing the hardware part of the cluster, let’s see how we can setup Kubernetes on Raspberry OS Lite</summary>
    <content type="html">&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/DSC00286-c2176fed/320.webp 320w, /generated/DSC00286-c2176fed/480.webp 480w, /generated/DSC00286-c2176fed/640.webp 640w, /generated/DSC00286-c2176fed/750.webp 750w, /generated/DSC00286-c2176fed/828.webp 828w, /generated/DSC00286-c2176fed/960.webp 960w, /generated/DSC00286-c2176fed/6000.webp 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Powered on cluster by night with only two cables attached&quot; src=&quot;/generated/DSC00286-c2176fed/6000.jpeg&quot; srcset=&quot;/generated/DSC00286-c2176fed/320.jpeg 320w, /generated/DSC00286-c2176fed/480.jpeg 480w, /generated/DSC00286-c2176fed/640.jpeg 640w, /generated/DSC00286-c2176fed/750.jpeg 750w, /generated/DSC00286-c2176fed/828.jpeg 828w, /generated/DSC00286-c2176fed/960.jpeg 960w, /generated/DSC00286-c2176fed/6000.jpeg 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; width=&quot;6000&quot; height=&quot;4000&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;After finishing the &lt;a href=&quot;portable-kubernetes-cluster-Raspberry4-rancher-k3s&quot;&gt;hardware&lt;/a&gt; part of the cluster, let’s see how to setup Kubernetes.&lt;/p&gt;
&lt;h1 id=&quot;versions&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;versions&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#versions&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Versions&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Raspberry Pi OS Lite 2020-08-20
&lt;a href=&quot;https://downloads.raspberrypi.org/raspios_lite_armhf/release_notes.txt&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Release Notes&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Rancher K3S 1.20.0
&lt;a href=&quot;https://rancher.com/products/k3s/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Product Page&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&quot;create-the-sd-cards&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;create the sd cards&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#create-the-sd-cards&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Create the SD Cards&lt;/h1&gt;
&lt;p&gt;List the partitions in MacOS Terminal using &lt;code&gt;diskutil list&lt;/code&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; diskutil&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; list&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/diskutil-volumes-c2176fed/320.webp 320w, /generated/diskutil-volumes-c2176fed/480.webp 480w, /generated/diskutil-volumes-c2176fed/640.webp 640w, /generated/diskutil-volumes-c2176fed/750.webp 750w, /generated/diskutil-volumes-c2176fed/828.webp 828w, /generated/diskutil-volumes-c2176fed/960.webp 960w, /generated/diskutil-volumes-c2176fed/1162.webp 1162w&quot; sizes=&quot;(min-width: 1162px) 1162px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Partition Table in MacOS Terminal&quot; src=&quot;/generated/diskutil-volumes-c2176fed/1162.png&quot; srcset=&quot;/generated/diskutil-volumes-c2176fed/320.png 320w, /generated/diskutil-volumes-c2176fed/480.png 480w, /generated/diskutil-volumes-c2176fed/640.png 640w, /generated/diskutil-volumes-c2176fed/750.png 750w, /generated/diskutil-volumes-c2176fed/828.png 828w, /generated/diskutil-volumes-c2176fed/960.png 960w, /generated/diskutil-volumes-c2176fed/1162.png 1162w&quot; sizes=&quot;(min-width: 1162px) 1162px, 100vw&quot; width=&quot;1162&quot; height=&quot;654&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Be really really (really!) sure, that you take the right volume. It also helps if its named properly in Finder.&lt;/p&gt;
&lt;p&gt;In this case it has the number &lt;strong&gt;2&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Lets unmount it:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; diskutil&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; unmountDisk&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /dev/disk2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now lets go to the &lt;strong&gt;danger zone&lt;/strong&gt;. &lt;code&gt;dd&lt;/code&gt; the downloaded &lt;code&gt;img&lt;/code&gt; file to the SD Card device.&lt;/p&gt;
&lt;p&gt;Be sure that you get the right volume number &lt;code&gt;/dev/rdisk-&gt;2&amp;#x3C;-&lt;/code&gt;. Using /dev/&lt;strong&gt;r&lt;/strong&gt;disk instead /dev/disk just makes the process a little faster.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; dd&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; if=2020-08-20-raspios-buster-arm64-lite.img&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; of=/dev/rdisk2&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bs=8m&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;p&gt;The output of &lt;code&gt;dd&lt;/code&gt; is quite reduced, can make one nervous…&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;… on MacOS hit Ctrl+T to get some information about the progress.&lt;/li&gt;
&lt;li&gt;… on most Linux distros there should be a command line option &lt;code&gt;status=progress&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; dd&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; if=/dev/urandom&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; of=/dev/null&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; count=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;131072&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bs=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1024&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; status=progress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;129695744&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bytes&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (130 &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;MB,&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 124&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; MiB&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) copied, 4 s, 32.4 MB/s &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# progress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;131072+0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; records&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;  # records read&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;131072+0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; records&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; out&lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt; # records written&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;134217728&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bytes&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (134 &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;MB,&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 128&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; MiB&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) copied, 4.13999 s, 32.4 MB/s  &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# totals, duration and speed&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;sub&gt;&lt;a href=&quot;https://askubuntu.com/questions/215505/how-do-you-monitor-the-progress-of-dd&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://askubuntu.com/questions/215505/how-do-you-monitor-the-progress-of-dd&lt;/a&gt;&lt;/sub&gt;
&lt;sub&gt;&lt;a href=&quot;https://www.raspberrypi.org/documentation/installation/installing-images/mac.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.raspberrypi.org/documentation/installation/installing-images/mac.md&lt;/a&gt;&lt;/sub&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Before pulling the SD Card out of the slot, we can already set some necessary boot options for running Kubernetes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;enable &lt;a href=&quot;https://01.org/linuxgraphics/gfx-docs/drm/admin-guide/cgroup-v1/cgroups.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;cgroups&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# Assuming that the new card has a boot partition that is mounted under /Volumes/boot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; echo&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -n&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1&quot;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; &gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /Volumes/boot/cmdline.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And let’s enable &lt;code&gt;ssh&lt;/code&gt; since we are in a headless mode:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# Assuming that the new card has a boot partition that is mounted under /Volumes/boot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; touch&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /Volumes/boot/ssh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;first-boot&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;first boot&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#first-boot&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;First boot&lt;/h1&gt;
&lt;p&gt;Put the cards into the Pis and start them up with the Ethernet cables connected.&lt;/p&gt;
&lt;p&gt;Find a way to determine the IP addresses, for example by logging into your router Web UI. Or if you like the more Linux way using &lt;a href=&quot;https://www.dnsstuff.com/ip-network-scanners&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;arp&lt;/code&gt;&lt;/a&gt; commands:&lt;/p&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Immediately change the password!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;The default password currently is “raspberry” - by the way.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ssh&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; pi@192.168.1.x&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; passwd&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Update the Pis&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; rpi-update&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; reboot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;k3s-first-contact&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;k3s first contact&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#k3s-first-contact&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;K3S first contact&lt;/h1&gt;
&lt;p&gt;Now we can check if the host OS is any good for running Rancher K3S.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; curl&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -sfL&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; https://raw.githubusercontent.com/rancher/k3s/master/contrib/util/check-config.sh&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; sh&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; -&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In my case it complained about, that &lt;a href=&quot;https://github.com/kubernetes/kubernetes/issues/71305#issuecomment-479558920&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;iptables is too new&lt;/a&gt;.
Raspberry OS has a simple way to fix this:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; update-alternatives&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --set&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; iptables&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /usr/sbin/iptables-legacy&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1 id=&quot;install-k3s&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;install k3s&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#install-k3s&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Install K3S&lt;/h1&gt;
&lt;p&gt;The actual setup is unbelievably easy, just run:&lt;/p&gt;
&lt;h2 id=&quot;master-node&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;master node&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#master-node&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Master Node&lt;/h2&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; curl&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -sfL&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; https://get.k3s.io&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; sh&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;worker-nodes&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;worker nodes&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#worker-nodes&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Worker Nodes&lt;/h2&gt;
&lt;p&gt;Get the node token on the master node&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; cat&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /var/lib/rancher/k3s/server/node-token&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run this command with the ip of the master node and the &lt;code&gt;node-token&lt;/code&gt; from above command.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; curl&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -sfL&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; http://get.k3s.io&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; K3S_URL&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;https://&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;MASTER&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; NODE&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; I&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;P&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;:6443&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                      K3S_TOKEN=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;NODE&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; TOKE&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sh&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; -&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Done!&lt;/p&gt;
&lt;p&gt;Don’t believe it?&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; kubectl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; nodes&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;NAME&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                 STATUS&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   ROLES&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                  AGE&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    VERSION&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;barbarachristensen&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   Ready&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    control-plane,master&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   4m4s&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   v1.20.0+k3s2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;janerose&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;             Ready&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;non&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                 4m4s&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   v1.20.0+k3s2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;maryireland&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;          Ready&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;non&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                 4m4s&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   v1.20.0+k3s2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;dianabeverley&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        Ready&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;    &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;non&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;e&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                 4m4s&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   v1.20.0+k3s2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;center&gt;😎&lt;/center&gt;
&lt;h1 id=&quot;convenience-features&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;convenience features&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#convenience-features&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Convenience Features&lt;/h1&gt;
&lt;h2 id=&quot;non-root-access&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;non root access&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#non-root-access&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Non-root access&lt;/h2&gt;
&lt;p&gt;Enable &lt;a href=&quot;https://rancher.com/docs/k3s/latest/en/cluster-access/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;non-root access&lt;/a&gt; to kubectl:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; cat&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /etc/rancher/k3s/k3s.yaml&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ~/.kube/config&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;bash-auto-completion&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;bash auto completion&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#bash-auto-completion&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Bash auto completion&lt;/h2&gt;
&lt;p&gt;Enable &lt;a href=&quot;https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;bash auto completion&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;sub&gt;The link contains also information for other OSes.&lt;/sub&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; apt-get&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bash-completion&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; echo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &apos;source &amp;#x3C;(kubectl completion bash)&apos;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; &gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;~/.bashrc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; echo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &apos;alias k=kubectl&apos;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; &gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;~/.bashrc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; echo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &apos;complete -F __start_kubectl k&apos;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; &gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;~/.bashrc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;shutdown-remotely&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;shutdown remotely&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#shutdown-remotely&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Shutdown remotely&lt;/h2&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;#!/bin/sh&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; nodes.lst`&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;	do&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; /usr/bin/ssh&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -t&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; $i&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /usr/bin/sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /sbin/poweroff&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;done&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; cat&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; nodes.lst&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;192.168.1.60&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;192.168.1.61&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;192.168.1.62&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;192.168.1.63&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To avoid entering a password for each node, copy the ssh key to each node:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; for&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; `&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; nodes.lst`&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;do&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; /usr/bin/ssh-copy-id &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$i&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;done&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;sub&gt;from: &lt;a href=&quot;https://www.simplylinuxfaq.com/2015/02/how-to-shutdown-remote-system-via-ssh-without-password.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.simplylinuxfaq.com/2015/02/how-to-shutdown-remote-system-via-ssh-without-password.html&lt;/a&gt;&lt;/sub&gt;&lt;/p&gt;
&lt;p&gt;After getting passwordless authentication to work it might be a good idea to &lt;a href=&quot;https://www.cyberciti.biz/faq/how-to-disable-ssh-password-login-on-linux/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;password authentication completely&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;related&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;related&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#related&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Related&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/posts/portable-kubernetes-cluster-Raspberry4-rancher-k3s/#page&quot;&gt;Portable Kubernetes Cluster based on Raspberry Pi 4 and Rancher K3S&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/posts/setup-k3s-on-raspberryos-lite/#page&quot;&gt;Setup mini Kubernetes Rancher K3S on Raspberry OS Lite&lt;/a&gt; (this)&lt;/li&gt;
&lt;li&gt;Storage class and nfs provisioner&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/posts/setting-up-a-four-times-redundant-gluster-with-mini-usb-sticks/#page&quot;&gt;Setting up a four times redundant gluster volume with mini USB sticks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Automatically provision Gluster volumes with Heketi&lt;/li&gt;
&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title type="html">Bringing my hacked weblog back to life</title>
    <link href="https://blog.loitzl.com/posts/bringing-my-hacked-weblog-back-to-life" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/bringing-my-hacked-weblog-back-to-life</id>
    <updated>2021-02-01T22:40:32.169Z</updated>
    <summary type="html">My wordpress blog has been hacked many years ago.</summary>
    <content type="html">&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/TitleImage-654d0bc3/320.webp 320w, /generated/TitleImage-654d0bc3/480.webp 480w, /generated/TitleImage-654d0bc3/640.webp 640w, /generated/TitleImage-654d0bc3/750.webp 750w, /generated/TitleImage-654d0bc3/828.webp 828w, /generated/TitleImage-654d0bc3/960.webp 960w, /generated/TitleImage-654d0bc3/1185.webp 1185w&quot; sizes=&quot;(min-width: 1185px) 1185px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Old and new side by sise&quot; src=&quot;/generated/TitleImage-654d0bc3/1185.png&quot; srcset=&quot;/generated/TitleImage-654d0bc3/320.png 320w, /generated/TitleImage-654d0bc3/480.png 480w, /generated/TitleImage-654d0bc3/640.png 640w, /generated/TitleImage-654d0bc3/750.png 750w, /generated/TitleImage-654d0bc3/828.png 828w, /generated/TitleImage-654d0bc3/960.png 960w, /generated/TitleImage-654d0bc3/1185.png 1185w&quot; sizes=&quot;(min-width: 1185px) 1185px, 100vw&quot; width=&quot;1185&quot; height=&quot;1079&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h1 id=&quot;youve-been-busted&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;youve been busted&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#youve-been-busted&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;You’ve been busted!&lt;/h1&gt;
&lt;p&gt;Due to poorly developed plugins, Wordpress blogs are prone to hacking.&lt;/p&gt;
&lt;p&gt;Luckily I wasn’t using any of those most dangerous Wordpress plugins mentioned in &lt;a href=&quot;https://wordpressforgood.com/most-dangerous-wordpress-plugins/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;this article&lt;/a&gt;, but just like many others, my weblog got abused for cross-site-request-forgeries and phishing - using php files that have been uploaded years before through exploits.&lt;/p&gt;
&lt;p&gt;At the end my account got locked and I lost interest a little.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;But, I still had some old backups.&lt;/p&gt;
&lt;p&gt;On my beloved &lt;a href=&quot;/posts/setup-k3s-on-raspberryos-lite/#page&quot;&gt;homegrown k8s cluster&lt;/a&gt; I was able to fire up some old &lt;a href=&quot;https://github.com/mloitzl/oldblogrestore/blob/master/wordpress-deployment.yml&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;php&lt;/a&gt; containers, a new &lt;a href=&quot;https://github.com/mloitzl/oldblogrestore/blob/master/mariadb-deployment.yml&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;mariadb&lt;/a&gt; and &lt;a href=&quot;https://github.com/mloitzl/oldblogrestore/blob/master/phpmyadmin-deployment.yml&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;phpmyadmin&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/tabletop-654d0bc3/320.webp 320w, /generated/tabletop-654d0bc3/480.webp 480w, /generated/tabletop-654d0bc3/640.webp 640w, /generated/tabletop-654d0bc3/725.webp 725w&quot; sizes=&quot;(min-width: 725px) 725px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Overview of the deployment&quot; src=&quot;/generated/tabletop-654d0bc3/725.png&quot; srcset=&quot;/generated/tabletop-654d0bc3/320.png 320w, /generated/tabletop-654d0bc3/480.png 480w, /generated/tabletop-654d0bc3/640.png 640w, /generated/tabletop-654d0bc3/725.png 725w&quot; sizes=&quot;(min-width: 725px) 725px, 100vw&quot; width=&quot;725&quot; height=&quot;537&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;
&lt;sub&gt;&lt;a href=&quot;https://app.cloudskew.com/viewer/f630bdcc-6dca-46cd-9168-9e9b762ad2dc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;CloudSkew&lt;/a&gt;&lt;/sub&gt;&lt;/p&gt;
&lt;p&gt;I restored the backup files into the persistent volume, imported the SQL dumps to mariadb, some more tweaks and we are ready to go.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; kustomize&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; edit&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; namespace&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; old-blog&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; kustomize&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; build&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; kubectl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; apply&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -f&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; -&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; kubectl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; run&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -i&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --rm&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --image=arm64v8/mariadb:10.5&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --restart=Never&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mariadb-client&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mysql&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -h&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mariadb&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -ppassword&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -e&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;create database wordpressdb&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; kubectl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; run&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -i&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --rm&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --image=arm64v8/mariadb:10.5&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --restart=Never&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mariadb-client&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mysql&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -h&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mariadb&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -ppassword&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; wordpressdb&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; wordpressdb.sql&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; kubectl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; run&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -i&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --rm&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --image=arm64v8/mariadb:10.5&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --restart=Never&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mariadb-client&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mysql&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -h&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mariadb&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -ppassword&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -e&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;create database gallery2db&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; kubectl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; run&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -i&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --rm&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --image=arm64v8/mariadb:10.5&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --restart=Never&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mariadb-client&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mysql&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -h&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mariadb&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -ppassword&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gallery2db&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; loitzlco-gallery2.sql&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Comes in quite quite handy for (manually) migrating and updating (dead links, etc.) to my new statically generated &lt;a href=&quot;https://github.com/mloitzl/lumen&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Lumen&lt;/a&gt;.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">Setting up a four times redundant gluster volume with mini USB sticks</title>
    <link href="https://blog.loitzl.com/posts/setting-up-a-four-times-redundant-gluster-with-mini-usb-sticks" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/setting-up-a-four-times-redundant-gluster-with-mini-usb-sticks</id>
    <updated>2021-01-28T22:40:32.169Z</updated>
    <summary type="html">What I really need is a super redundant storage cluster on my Pi cluster using plain USB sticks.</summary>
    <content type="html">&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/VerbatimUSB30-7e89651d/320.webp 320w, /generated/VerbatimUSB30-7e89651d/480.webp 480w, /generated/VerbatimUSB30-7e89651d/640.webp 640w, /generated/VerbatimUSB30-7e89651d/657.webp 657w&quot; sizes=&quot;(min-width: 657px) 657px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;4 USB Sticks, one for each node&quot; src=&quot;/generated/VerbatimUSB30-7e89651d/657.png&quot; srcset=&quot;/generated/VerbatimUSB30-7e89651d/320.png 320w, /generated/VerbatimUSB30-7e89651d/480.png 480w, /generated/VerbatimUSB30-7e89651d/640.png 640w, /generated/VerbatimUSB30-7e89651d/657.png 657w&quot; sizes=&quot;(min-width: 657px) 657px, 100vw&quot; width=&quot;657&quot; height=&quot;609&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;What I really really need is a super redundant storage cluster on my Pi cluster using plain USB sticks.&lt;/p&gt;
&lt;p&gt;This might sound a little bit over-engineered, but having a &lt;a href=&quot;https://www.gluster.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Gluster&lt;/a&gt; with 4 USB sticks - one for each Raspberry - allows to run the Cluster with some nodes switched off to safe some energy.&lt;/p&gt;
&lt;p&gt;The architecture is as simple as this: Gluster - Heketi Provisioner - Kubernetes Storage Class&lt;/p&gt;
&lt;p&gt;The first step (this article) is to create the storage cluster using USB sticks.&lt;/p&gt;
&lt;p&gt;This is pretty straight forward and completely based on other blog articles cited at the end.&lt;/p&gt;
&lt;h2 id=&quot;setup-the-gluster-server&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;setup the gluster server&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#setup-the-gluster-server&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Setup the Gluster Server&lt;/h2&gt;
&lt;p&gt;Install the &lt;code&gt;glusterfs-server&lt;/code&gt; package on each node&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; apt-get&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; install&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; glusterfs-server&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Host file entries allow all nodes to find each other&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; nano&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /etc/hosts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;192.168.1.60&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    gluster0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;192.168.1.61&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    gluster1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;192.168.1.62&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    gluster2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;192.168.1.63&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    gluster3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Check if &lt;code&gt;glusterd.service&lt;/code&gt; has been correctly set-up …&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; systemctl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; status&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; glusterd.service&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;●&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; glusterd.service&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; GlusterFS,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; clustered&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; file-system&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; server&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;   Loaded:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; loaded&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (/lib/systemd/system/glusterd.service; &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;disabled&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;vendor&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; preset:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; enabled&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;   Active:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; inactive&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (dead)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;     Docs:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; man:glusterd&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;… then start and enable the service on each node.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; systemctl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; start&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; glusterd.service&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; systemctl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; enable&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; glusterd.service&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now probe the nodes&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; peer&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; probe&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;peer&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; probe:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; success.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; peer&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; status&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Number&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Peers:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Hostname:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 192.168.1.61&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Uuid:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; e34e779c-f0f4-453b-bd9f-103654470614&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;State:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Peer&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Cluster&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (Connected)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Other&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; names:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;gluster1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Hostname:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Uuid:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; cc244b01-1884-4d2d-a213-29f283f3067a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;State:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Peer&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Cluster&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (Connected)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Hostname:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Uuid:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; a2faf317-47bb-414b-9a87-7e2240b210cd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;State:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Peer&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Cluster&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (Connected)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;prepare-the-usb-sticks&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;prepare the usb sticks&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#prepare-the-usb-sticks&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Prepare the USB Sticks&lt;/h2&gt;
&lt;p&gt;The USB sticks need to be formatted for Gluster. First list all block devices with &lt;code&gt;lsblk&lt;/code&gt; and be sure to pick the right one&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; lsblk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;NAME&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        MAJ:MIN&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; RM&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;  SIZE&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; RO&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; TYPE&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; MOUNTPOINT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;sda&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;           8:0&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;    1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 57.6G&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;  0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; disk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-sda1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        8:1    &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 57.6G  &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; part&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;mmcblk0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;     179:0    &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 29.8G  &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; disk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-mmcblk0p1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 179:1    &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;  256M  &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; part /boot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-mmcblk0p2&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 179:2&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 29.6G&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;  0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; part&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run the following commands to partition the USB sticks&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; fdisk&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -w&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; auto&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /dev/sda&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Welcome&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; to&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; fdisk&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (util-linux &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;2.33.1&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;).&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Changes&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; will&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; remain&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; in&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; memory&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; only,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; until&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; you&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; decide&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; to&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; write&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; them.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Be&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; careful&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; before&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; using&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; the&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; write&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; command.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Command&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (m &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; help&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;): g&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Created&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; GPT&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; disklabel&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (GUID: &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;0F840961-BAB8-064B-ABFE-C02CA2D346A0&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;).&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;The&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; old&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; dos&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; signature&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; will&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; be&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; removed&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; by&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; write&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; command.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Command&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (m &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; help&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;): n&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Partition&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (1-128, &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;First&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sector&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (2048-120831966, &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 2048&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Last&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sector,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; +/-sectors&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; or&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; +/-size{K,M,G,T,P}&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (2048-120831966, &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 120831966&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Created&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; a&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; partition&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; type&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &apos;Linux filesystem&apos;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; and&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; size&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 57.6&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; GiB.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Command&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (m &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; help&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;): w&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;The&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; partition&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; table&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; has&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; been&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; altered.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Calling&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ioctl&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; re-read&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; partition&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; table.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Syncing&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; disks.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The newly created partition can then be formatted with the XFS filesystem&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mkfs.xfs&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -f&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -L&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; glstrbrck0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /dev/sda1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;meta-data&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;/dev/sda1&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;              isize&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;512&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    agcount&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;4,&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; agsize&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;3775935&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; blks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;         =&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                       sectsz=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;512&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   attr=2,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; projid32bit=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;         =&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                       crc=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        finobt=1,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sparse=1,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; rmapbt=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;         =&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                       reflink=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;     =&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                       bsize=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;4096&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   blocks=15103739,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; imaxpct=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;25&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;         =&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                       sunit=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      swidth=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; blks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;naming&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   =version&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 2&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;              bsize=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;4096&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   ascii-ci=0,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ftype=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      =internal&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; log&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;           bsize=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;4096&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   blocks=7374,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; version=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;         =&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                       sectsz=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;512&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   sunit=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; blks,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; lazy-count=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;realtime&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; =none&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                   extsz=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;4096&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   blocks=0,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; rtextents=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create the mountpoint&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mkdir&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -p&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /data/glusterfs/glstrbrck/0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Determine the partition UUID and write it to the fstab so that its get mounted automatically when booting&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; printf&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; $(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; blkid&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -o&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; export&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /dev/sda1&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;grep&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; PARTUUID&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot; /data/glusterfs/glstrbrck/0 xfs defaults,noatime 1 2\n&quot;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; tee&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -a&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /etc/fstab&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And mount (or reboot)&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mount&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /data/glusterfs/glstrbrck/0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;-o&lt;/code&gt;flag of &lt;code&gt;lsblk&lt;/code&gt; can be used show the details of the newly created partition:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; lsblk&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -o&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; name,size,type,fstype,mountpoint,label&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;NAME&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;         SIZE&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; TYPE&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; FSTYPE&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; MOUNTPOINT&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                  LABEL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;sda&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;         57.6G&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; disk&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;                                    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-sda1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;      57.6G part xfs    /data/glusterfs/glstrbrck/0 glstrbrck0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;mmcblk0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;     29.8G disk                                    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-mmcblk0p1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;  256M part vfat   /boot                       boot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-mmcblk0p2&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 29.6G&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; part&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ext4&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   /&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                           rootfs&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;center&gt;All right so far&lt;/center&gt;
&lt;h2 id=&quot;create-the-gluster-volume&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;create the gluster volume&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#create-the-gluster-volume&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Create the Gluster Volume&lt;/h2&gt;
&lt;p&gt;After performing the steps on all nodes, a new Gluster Volume can be created - with 4 replicas in my case.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; volume&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; create&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; glustervol0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; replica&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster0:/data/glusterfs/glstrbrck/0/brick&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster1:/data/glusterfs/glstrbrck/0/brick&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster2:/data/glusterfs/glstrbrck/0/brick&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster3:/data/glusterfs/glstrbrck/0/brick&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; volume&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; start&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; glustervol0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lets check the results:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;List the Volumes…&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; volume&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;glustervol0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;… and display volume details&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; volume&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; info&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; glustervol0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Volume&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Name:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; glustervol0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Type:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Replicate&lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;       # &amp;#x3C;- A replicated volume&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Volume&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ID:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 066c49bb-9c6b-48b0-8f4a-2e9c72e1aa40&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Status:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Started&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Snapshot&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Count:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Number&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Bricks:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; x&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 4&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Transport-type:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; tcp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Bricks:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Brick1:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster0:/data/glusterfs/glstrbrck/0/brick&lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;  # &amp;#x3C;- 4 bricks&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Brick2:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster1:/data/glusterfs/glstrbrck/0/brick&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Brick3:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster2:/data/glusterfs/glstrbrck/0/brick&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Brick4:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster3:/data/glusterfs/glstrbrck/0/brick&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Options&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Reconfigured:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;transport.address-family:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; inet&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;nfs.disable:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; on&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;performance.client-io-threads:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; off&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;center&gt;😎 - Awesome&lt;/center&gt;
&lt;h2 id=&quot;some-tests&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;some tests&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#some-tests&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Some Tests&lt;/h2&gt;
&lt;p&gt;Mount the the gluster volume on one of the nodes:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mkdir&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /storage-pool&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mount&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -t&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; glusterfs&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster0:/glustervol0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /storage-pool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create some files&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; cd&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /storage-pool/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; touch&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; file_{0..9}.test&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mount the gluster volume on another host, and check the result.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; mount&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -t&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; glusterfs&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; gluster1:/glustervol0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /storage-pool&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; cd&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /storage-pool&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ls&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;storage-pool&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; $ &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;ls&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -la&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;drwxr-xr-x&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;  3&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 4096&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Jan&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 25&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 16:47&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; .&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;drwxr-xr-x&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 23&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 4096&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Jan&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 17&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 17:52&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ..&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-rw-r--r--&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;  1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Jan&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 17&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 17:53&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; file_0.test&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-rw-r--r--&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;  1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Jan&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 17&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 17:53&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; file_1.test&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-rw-r--r--&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;  1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Jan&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 17&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 17:53&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; file_2.test&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-rw-r--r--&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;  1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Jan&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 17&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 17:53&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; file_3.test&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-rw-r--r--&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;  1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Jan&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 17&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 17:53&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; file_4.test&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-rw-r--r--&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;  1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Jan&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 17&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 17:53&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; file_5.test&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-rw-r--r--&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;  1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Jan&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 17&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 17:53&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; file_6.test&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-rw-r--r--&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;  1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Jan&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 17&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 17:53&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; file_7.test&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-rw-r--r--&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;  1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Jan&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 17&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 17:53&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; file_8.test&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;-rw-r--r--&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;  1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; root&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;    0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; Jan&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 17&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 17:53&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; file_9.test&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That works!&lt;/p&gt;
&lt;h2 id=&quot;performance&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;performance&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#performance&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Performance&lt;/h2&gt;
&lt;p&gt;Now lets check the performance…&lt;/p&gt;
&lt;h3 id=&quot;writing-random-data&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;writing random data&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#writing-random-data&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Writing random data&lt;/h3&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; dd&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; if=/dev/urandom&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; of=/storage-pool/file1.rnd&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; count=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;65536&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bs=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1024&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;65536+0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; records&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;65536+0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; records&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; out&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;67108864&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bytes&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (67 &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;MB,&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 64&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; MiB&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) copied, 14.5248 s, 4.6 MB/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;… increasing the block size helps.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; dd&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; if=/dev/urandom&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; of=/storage-pool/file2.rnd&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; count=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;512&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bs=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;131072&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;512+0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; records&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;512+0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; records&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; out&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;67108864&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bytes&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (67 &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;MB,&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 64&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; MiB&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) copied, 2.37264 s, 28.3 MB/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Whats actually the read speed of urandom?&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; dd&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; if=/dev/urandom&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; of=/dev/null&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; count=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;65536&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bs=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1024&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;65536+0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; records&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;65536+0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; records&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; out&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;67108864&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bytes&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (67 &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;MB,&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 64&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; MiB&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) copied, 1.32923 s, 50.5 MB/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pretty nice for an embedded device.&lt;/p&gt;
&lt;h3 id=&quot;reading-data&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;reading data&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#reading-data&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Reading data&lt;/h3&gt;
&lt;p&gt;Read a file…&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; dd&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; if=/storage-pool/file2.rnd&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; of=/dev/null&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bs=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;131072&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;512+0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; records&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;512+0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; records&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; out&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;67108864&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bytes&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (67 &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;MB,&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 64&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; MiB&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) copied, 0.595213 s, 113 MB/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;… and read the file a second time reveals the caching performance.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; dd&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; if=/storage-pool/file2.rnd&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; of=/dev/null&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bs=&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;131072&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;512+0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; records&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;512+0&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; records&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; out&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;67108864&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; bytes&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (67 &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;MB,&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt; 64&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; MiB&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) copied, 0.0385229 s, 1.7 GB/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Setting up a 4 times redundant storage array with Gluster went pretty straight forward due to the follwing awesome articles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://godatadriven.com/blog/building-a-raspberry-pi-storage-cluster-to-run-big-data-tools-at-home/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Building a Raspberry Pi storage cluster to run Big Data tools at home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gopeedesignstudio.com/2018/07/13/glusterfs-on-arm/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;GlusterFS on ARM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-create-a-redundant-storage-pool-using-glusterfs-on-ubuntu-18-04#step-4-%E2%80%94-creating-a-storage-volume&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;How To Create a Redundant Storage Pool Using GlusterFS on Ubuntu 18.04&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&quot;related&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;related&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#related&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Related&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/posts/portable-kubernetes-cluster-Raspberry4-rancher-k3s/#page&quot;&gt;Portable Kubernetes Cluster based on Raspberry Pi 4 and Rancher K3S&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/posts/setup-k3s-on-raspberryos-lite/#page&quot;&gt;Setup mini Kubernetes Rancher K3S on Raspberry OS Lite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Storage class and nfs provisioner&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/posts/setting-up-a-four-times-redundant-gluster-with-mini-usb-sticks/#page&quot;&gt;Setting up a four times redundant gluster volume with mini USB sticks&lt;/a&gt; (this)&lt;/li&gt;
&lt;li&gt;Automatically provision Gluster volumes with Heketi&lt;/li&gt;
&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title type="html">Portable Kubernetes Cluster based on Raspberry Pi 4 and Rancher K3S</title>
    <link href="https://blog.loitzl.com/posts/portable-kubernetes-cluster-Raspberry4-rancher-k3s" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/portable-kubernetes-cluster-Raspberry4-rancher-k3s</id>
    <updated>2021-01-24T22:40:32.169Z</updated>
    <summary type="html">Complete description for creating my portable Kubernetes Cluster based on Raspberry Pi 4 and Rancher K3s in Raspberry OS lite.</summary>
    <content type="html">&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/DSC00286-2e869cc8/320.webp 320w, /generated/DSC00286-2e869cc8/480.webp 480w, /generated/DSC00286-2e869cc8/640.webp 640w, /generated/DSC00286-2e869cc8/750.webp 750w, /generated/DSC00286-2e869cc8/828.webp 828w, /generated/DSC00286-2e869cc8/960.webp 960w, /generated/DSC00286-2e869cc8/6000.webp 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Powered on cluster by night with only two cables attached&quot; src=&quot;/generated/DSC00286-2e869cc8/6000.jpeg&quot; srcset=&quot;/generated/DSC00286-2e869cc8/320.jpeg 320w, /generated/DSC00286-2e869cc8/480.jpeg 480w, /generated/DSC00286-2e869cc8/640.jpeg 640w, /generated/DSC00286-2e869cc8/750.jpeg 750w, /generated/DSC00286-2e869cc8/828.jpeg 828w, /generated/DSC00286-2e869cc8/960.jpeg 960w, /generated/DSC00286-2e869cc8/6000.jpeg 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; width=&quot;6000&quot; height=&quot;4000&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Since literally everbody I know is currently working on a cloud@home project in some form I also decided to start working a long planned project: a portable kubernetes cluster.&lt;/p&gt;
&lt;p&gt;And also a former &lt;a href=&quot;https://sandrofelder.ch/building-your-own-private-cloud-with-raspberry-pi-4-and-kubernetes/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;colleague&lt;/a&gt; gave me the last push for it - thanks 😉&lt;/p&gt;
&lt;h1 id=&quot;portability&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;portability&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#portability&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Portability&lt;/h1&gt;
&lt;p&gt;Currently, portability means, that only 2 cables - power and network - are connected.&lt;/p&gt;
&lt;p&gt;A later addition I am planning is attaching the cluster to a mobile router. The question ist, if the POE switch can deliver the necessary additional power for this.&lt;/p&gt;
&lt;p&gt;And, the 52Pi rack tower has a handle to carry it around - or throw it out of the window - depends on the use case.&lt;/p&gt;
&lt;p&gt;This will become a series of articles, lets start with the hardware.&lt;/p&gt;
&lt;h1 id=&quot;hardware&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;hardware&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#hardware&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Hardware&lt;/h1&gt;
&lt;h2 id=&quot;parts-list&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;parts list&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#parts-list&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Parts List&lt;/h2&gt;























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th align=&quot;center&quot;&gt;#&lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Part&lt;/th&gt;&lt;th align=&quot;right&quot;&gt;each&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;4&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;a href=&quot;https://www.raspberrypi.org/products/raspberry-pi-4-model-b/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Raspberry Pi 4 8GB Model B  (ARMv8)&lt;/a&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;CHF 89.90&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;4&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;a href=&quot;https://www.verbatim.de/de/prod/verbatim-store-n-stay-nano-usb-32-gen-1-drive-64gb-98711/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Verbatim Nano 64GB USB Sticks&lt;/a&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;CHF 11.95&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;1&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;a href=&quot;https://wiki.52pi.com/index.php/Rack_Tower_SKU:_ZP-0088&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;52Pi ZP-0088 Rack Tower&lt;/a&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;CHF 35.00&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;1&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;a href=&quot;https://www.tp-link.com/us/business-networking/poe-switch/tl-sg1005p/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;POE Switch Tp-Link TL-SG1005P&lt;/a&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;CHF 51.30&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;4&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;a href=&quot;http://www.logilink.de/content/support/kataloge.htm&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;POE Cables LogiLink (U/FTP, Kat. 6a, 25cm)&lt;/a&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;CHF 5.90&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;3&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;a href=&quot;https://www.uctronics.com/tools-and-accessories/pi-accessories/poe-hat-for-raspberry-pi-4-uctronics-mini-power-over-ethernet-expansion-board-for-raspberry-pi-4-b-3-b.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;POE Hat Type U6109&lt;/a&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;CHF 23.90&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;1&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;a href=&quot;https://www.uctronics.com/poe-hat-for-raspberry-pi-4-uctronics-mini-power-over-ethernet-expansion-board-for-raspberry-pi-4-b-3-b-with-cooling-fan.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;POE Hat Type U6110&lt;/a&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;CHF 25.90&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;1&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;a href=&quot;https://www.aliexpress.com/w/wholesale-dupont-connector-pin.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Dupont Pin Row&lt;/a&gt;&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;CHF 0.05&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td align=&quot;center&quot;&gt;&lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Total&lt;/td&gt;&lt;td align=&quot;right&quot;&gt;&lt;strong&gt;CHF 614.95&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/DSC00267-2e869cc8/320.webp 320w, /generated/DSC00267-2e869cc8/480.webp 480w, /generated/DSC00267-2e869cc8/640.webp 640w, /generated/DSC00267-2e869cc8/750.webp 750w, /generated/DSC00267-2e869cc8/828.webp 828w, /generated/DSC00267-2e869cc8/960.webp 960w, /generated/DSC00267-2e869cc8/1618.webp 1618w&quot; sizes=&quot;(min-width: 1618px) 1618px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;All parts flat&quot; src=&quot;/generated/DSC00267-2e869cc8/1618.jpeg&quot; srcset=&quot;/generated/DSC00267-2e869cc8/320.jpeg 320w, /generated/DSC00267-2e869cc8/480.jpeg 480w, /generated/DSC00267-2e869cc8/640.jpeg 640w, /generated/DSC00267-2e869cc8/750.jpeg 750w, /generated/DSC00267-2e869cc8/828.jpeg 828w, /generated/DSC00267-2e869cc8/960.jpeg 960w, /generated/DSC00267-2e869cc8/1618.jpeg 1618w&quot; sizes=&quot;(min-width: 1618px) 1618px, 100vw&quot; width=&quot;1618&quot; height=&quot;921&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h2 id=&quot;dupont-pins-on-the-u6109&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;dupont pins on the u6109&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#dupont-pins-on-the-u6109&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Dupont Pins on the U6109&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://www.uctronics.com/tools-and-accessories/pi-accessories/poe-hat-for-raspberry-pi-4-uctronics-mini-power-over-ethernet-expansion-board-for-raspberry-pi-4-b-3-b.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;U6109&lt;/a&gt; actually has two rows for connectors, mine had no connectors soldered in - unfortunately.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/U6109-2e869cc8/320.webp 320w, /generated/U6109-2e869cc8/423.webp 423w&quot; sizes=&quot;(min-width: 423px) 423px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;U6109 with missing connectors&quot; src=&quot;/generated/U6109-2e869cc8/423.png&quot; srcset=&quot;/generated/U6109-2e869cc8/320.png 320w, /generated/U6109-2e869cc8/423.png 423w&quot; sizes=&quot;(min-width: 423px) 423px, 100vw&quot; width=&quot;423&quot; height=&quot;235&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;My soldering skills are a little dated, but I took my chances - and it worked out nicely.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/DSC00268-2e869cc8/320.webp 320w, /generated/DSC00268-2e869cc8/480.webp 480w, /generated/DSC00268-2e869cc8/640.webp 640w, /generated/DSC00268-2e869cc8/750.webp 750w, /generated/DSC00268-2e869cc8/828.webp 828w, /generated/DSC00268-2e869cc8/960.webp 960w, /generated/DSC00268-2e869cc8/6000.webp 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Soldering dupont connector pins onto the POE hat&quot; src=&quot;/generated/DSC00268-2e869cc8/6000.jpeg&quot; srcset=&quot;/generated/DSC00268-2e869cc8/320.jpeg 320w, /generated/DSC00268-2e869cc8/480.jpeg 480w, /generated/DSC00268-2e869cc8/640.jpeg 640w, /generated/DSC00268-2e869cc8/750.jpeg 750w, /generated/DSC00268-2e869cc8/828.jpeg 828w, /generated/DSC00268-2e869cc8/960.jpeg 960w, /generated/DSC00268-2e869cc8/6000.jpeg 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; width=&quot;6000&quot; height=&quot;4000&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/DSC00270-2e869cc8/320.webp 320w, /generated/DSC00270-2e869cc8/480.webp 480w, /generated/DSC00270-2e869cc8/640.webp 640w, /generated/DSC00270-2e869cc8/750.webp 750w, /generated/DSC00270-2e869cc8/828.webp 828w, /generated/DSC00270-2e869cc8/960.webp 960w, /generated/DSC00270-2e869cc8/6000.webp 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Soldered pins from top&quot; src=&quot;/generated/DSC00270-2e869cc8/6000.jpeg&quot; srcset=&quot;/generated/DSC00270-2e869cc8/320.jpeg 320w, /generated/DSC00270-2e869cc8/480.jpeg 480w, /generated/DSC00270-2e869cc8/640.jpeg 640w, /generated/DSC00270-2e869cc8/750.jpeg 750w, /generated/DSC00270-2e869cc8/828.jpeg 828w, /generated/DSC00270-2e869cc8/960.jpeg 960w, /generated/DSC00270-2e869cc8/6000.jpeg 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; width=&quot;6000&quot; height=&quot;4000&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Fan and LED connector cables can now easily be attached to the POE powered Raspberry.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/DSC00278-2e869cc8/320.webp 320w, /generated/DSC00278-2e869cc8/480.webp 480w, /generated/DSC00278-2e869cc8/640.webp 640w, /generated/DSC00278-2e869cc8/750.webp 750w, /generated/DSC00278-2e869cc8/828.webp 828w, /generated/DSC00278-2e869cc8/960.webp 960w, /generated/DSC00278-2e869cc8/6000.webp 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;LED and ventilator attached to the modified POE hat&quot; src=&quot;/generated/DSC00278-2e869cc8/6000.jpeg&quot; srcset=&quot;/generated/DSC00278-2e869cc8/320.jpeg 320w, /generated/DSC00278-2e869cc8/480.jpeg 480w, /generated/DSC00278-2e869cc8/640.jpeg 640w, /generated/DSC00278-2e869cc8/750.jpeg 750w, /generated/DSC00278-2e869cc8/828.jpeg 828w, /generated/DSC00278-2e869cc8/960.jpeg 960w, /generated/DSC00278-2e869cc8/6000.jpeg 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; width=&quot;6000&quot; height=&quot;4000&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Speaking of ventilation: the 52Pi rack tower ventilator is suprisingly quiet, but powerfull - so having it in the same room is not disturbing at all.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/U6110-2e869cc8/320.webp 320w, /generated/U6110-2e869cc8/460.webp 460w&quot; sizes=&quot;(min-width: 460px) 460px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;U6110&quot; src=&quot;/generated/U6110-2e869cc8/460.png&quot; srcset=&quot;/generated/U6110-2e869cc8/320.png 320w, /generated/U6110-2e869cc8/460.png 460w&quot; sizes=&quot;(min-width: 460px) 460px, 100vw&quot; width=&quot;460&quot; height=&quot;459&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;I removed the fan from the &lt;a href=&quot;https://www.uctronics.com/poe-hat-for-raspberry-pi-4-uctronics-mini-power-over-ethernet-expansion-board-for-raspberry-pi-4-b-3-b-with-cooling-fan.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;U6110&lt;/a&gt;, because they make a quite annoying sound.&lt;/p&gt;
&lt;h2 id=&quot;accessible-sd-cards&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;accessible sd cards&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#accessible-sd-cards&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Accessible SD Cards&lt;/h2&gt;
&lt;p&gt;A quite handy feature of the 52Pi rack tower are the SD card adapters. The card slots would be very hard to reach, when the case is fully assembled.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/DSC00272-2e869cc8/320.webp 320w, /generated/DSC00272-2e869cc8/480.webp 480w, /generated/DSC00272-2e869cc8/640.webp 640w, /generated/DSC00272-2e869cc8/750.webp 750w, /generated/DSC00272-2e869cc8/828.webp 828w, /generated/DSC00272-2e869cc8/960.webp 960w, /generated/DSC00272-2e869cc8/6000.webp 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;The SD card adapter makes the cards accessible from the front&quot; src=&quot;/generated/DSC00272-2e869cc8/6000.jpeg&quot; srcset=&quot;/generated/DSC00272-2e869cc8/320.jpeg 320w, /generated/DSC00272-2e869cc8/480.jpeg 480w, /generated/DSC00272-2e869cc8/640.jpeg 640w, /generated/DSC00272-2e869cc8/750.jpeg 750w, /generated/DSC00272-2e869cc8/828.jpeg 828w, /generated/DSC00272-2e869cc8/960.jpeg 960w, /generated/DSC00272-2e869cc8/6000.jpeg 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; width=&quot;6000&quot; height=&quot;4000&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h2 id=&quot;mount-the-poe-switch&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;mount the poe switch&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#mount-the-poe-switch&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Mount the POE Switch&lt;/h2&gt;
&lt;p&gt;A simple wooden plate with a bunch of holes is connected to the base of the 52Pi rack tower using 4 blue cable ties.&lt;/p&gt;
&lt;p&gt;The 2 Screws in the middle are connected the wall-mount recess of the POE Switch.&lt;/p&gt;
&lt;p&gt;An acrylic plate would be nice, but I don’t have access to a laser-cutter.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/DSC00275-2e869cc8/320.webp 320w, /generated/DSC00275-2e869cc8/480.webp 480w, /generated/DSC00275-2e869cc8/640.webp 640w, /generated/DSC00275-2e869cc8/750.webp 750w, /generated/DSC00275-2e869cc8/828.webp 828w, /generated/DSC00275-2e869cc8/960.webp 960w, /generated/DSC00275-2e869cc8/6000.webp 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Simple wooden plate to attach the POE Switch using the wall-mount holes&quot; src=&quot;/generated/DSC00275-2e869cc8/6000.jpeg&quot; srcset=&quot;/generated/DSC00275-2e869cc8/320.jpeg 320w, /generated/DSC00275-2e869cc8/480.jpeg 480w, /generated/DSC00275-2e869cc8/640.jpeg 640w, /generated/DSC00275-2e869cc8/750.jpeg 750w, /generated/DSC00275-2e869cc8/828.jpeg 828w, /generated/DSC00275-2e869cc8/960.jpeg 960w, /generated/DSC00275-2e869cc8/6000.jpeg 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; width=&quot;6000&quot; height=&quot;4000&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h2 id=&quot;fully-assembled&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;fully assembled&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#fully-assembled&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Fully assembled&lt;/h2&gt;
&lt;p&gt;The fully assembled case with the 4 USB Sticks for the &lt;a href=&quot;setting-up-a-four-times-redundant-gluster-with-mini-usb-sticks&quot;&gt;Storage Cluster&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/DSC00281-2e869cc8/320.webp 320w, /generated/DSC00281-2e869cc8/480.webp 480w, /generated/DSC00281-2e869cc8/640.webp 640w, /generated/DSC00281-2e869cc8/750.webp 750w, /generated/DSC00281-2e869cc8/828.webp 828w, /generated/DSC00281-2e869cc8/960.webp 960w, /generated/DSC00281-2e869cc8/6000.webp 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Fully assembled case with switch, cables, USB sticks and the raspberries&quot; src=&quot;/generated/DSC00281-2e869cc8/6000.jpeg&quot; srcset=&quot;/generated/DSC00281-2e869cc8/320.jpeg 320w, /generated/DSC00281-2e869cc8/480.jpeg 480w, /generated/DSC00281-2e869cc8/640.jpeg 640w, /generated/DSC00281-2e869cc8/750.jpeg 750w, /generated/DSC00281-2e869cc8/828.jpeg 828w, /generated/DSC00281-2e869cc8/960.jpeg 960w, /generated/DSC00281-2e869cc8/6000.jpeg 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; width=&quot;6000&quot; height=&quot;4000&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Looks quite shiny by night 🤓&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/DSC00286-2e869cc8/320.webp 320w, /generated/DSC00286-2e869cc8/480.webp 480w, /generated/DSC00286-2e869cc8/640.webp 640w, /generated/DSC00286-2e869cc8/750.webp 750w, /generated/DSC00286-2e869cc8/828.webp 828w, /generated/DSC00286-2e869cc8/960.webp 960w, /generated/DSC00286-2e869cc8/6000.webp 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Powered on cluster by night with only two cables attached&quot; src=&quot;/generated/DSC00286-2e869cc8/6000.jpeg&quot; srcset=&quot;/generated/DSC00286-2e869cc8/320.jpeg 320w, /generated/DSC00286-2e869cc8/480.jpeg 480w, /generated/DSC00286-2e869cc8/640.jpeg 640w, /generated/DSC00286-2e869cc8/750.jpeg 750w, /generated/DSC00286-2e869cc8/828.jpeg 828w, /generated/DSC00286-2e869cc8/960.jpeg 960w, /generated/DSC00286-2e869cc8/6000.jpeg 6000w&quot; sizes=&quot;(min-width: 6000px) 6000px, 100vw&quot; width=&quot;6000&quot; height=&quot;4000&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;h1 id=&quot;related&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;related&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#related&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Related&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/posts/portable-kubernetes-cluster-Raspberry4-rancher-k3s/#page&quot;&gt;Portable Kubernetes Cluster based on Raspberry Pi 4 and Rancher K3S&lt;/a&gt; (this)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/posts/setup-k3s-on-raspberryos-lite/#page&quot;&gt;Setup mini Kubernetes Rancher K3S on Raspberry OS Lite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Storage class and nfs provisioner&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/posts/setting-up-a-four-times-redundant-gluster-with-mini-usb-sticks/#page&quot;&gt;Setting up a four times redundant gluster volume with mini USB sticks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Automatically provision Gluster volumes with Heketi&lt;/li&gt;
&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title type="html">Gatsby Plugin Sharp not building on Raspberry PI (arm64)</title>
    <link href="https://blog.loitzl.com/posts/gatsby-plugin-sharp-not-building-on-raspberry-pi-64" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/gatsby-plugin-sharp-not-building-on-raspberry-pi-64</id>
    <updated>2021-01-08T22:40:32.169Z</updated>
    <summary type="html">The gatsby plugin for &apos;sharp&apos; depends on Libvips and for some reason the `Dockerfile.production` from gatsby-starter-lumen does not build on my Raspberry Pi 4.</summary>
    <content type="html">&lt;p&gt;The gatsby plugin Sharp depends on &lt;a href=&quot;https://libvips.github.io/libvips/install.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Libvips&lt;/a&gt; and for some reason the &lt;code&gt;Dockerfile.production&lt;/code&gt; from &lt;a href=&quot;https://www.gatsbyjs.com/starters/alxshelepenok/gatsby-starter-lumen&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;gatsby-starter-lumen&lt;/a&gt; it does not build on my Raspberry Pi 4.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;c&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;make: Entering directory &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&apos;/usr/src/app/node_modules/sharp/build&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  CC&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(target) Release&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;obj.target&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;nothing&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;node&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;addon&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;api&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;nothing.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  AR&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(target) Release&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;obj.target&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;node&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;addon&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;api&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;nothing.a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  COPY Release&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;nothing.a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  TOUCH Release&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;obj.target&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;libvips&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;cpp.stamp&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  CXX&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(target) Release&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;obj.target&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;sharp&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;src&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;common.o&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;..&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;src&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;common.cc:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;24&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: fatal error: vips&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;vips8: No such file or directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D33682&quot;&gt;   24&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; #include &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;vips&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;vips8&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;      |&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;          ^~~~~~~~~~~~&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;compilation terminated.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;make: &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;***&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;sharp&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;target&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;mk&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;137&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;: Release&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;obj&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;target&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;sharp&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;src&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;common&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;o&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;] Error &lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;make: Leaving directory &lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&apos;/usr/src/app/node_modules/sharp/build&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I am pretty shure, that there are other ways, but adding a global package &lt;code&gt;vips-dev&lt;/code&gt; solved the problem:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;docker&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;RUN&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; apk add --update --no-cache --repository http://dl-3.alpinelinux.org/alpine/edge/community --repository http://dl-3.alpinelinux.org/alpine/edge/main vips-dev&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The build takes very long (44 minutes), since literally everthing is compiled from scratch.&lt;/p&gt;
&lt;p&gt;But this can be improved by using Docker caching or probably a base image.&lt;/p&gt;
&lt;p&gt;More to come!&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">Kubernetes Version 1.20.0 breaks nfs provisioner</title>
    <link href="https://blog.loitzl.com/posts/k8s-1.20-breaks-nfs-client-provisioner" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/k8s-1.20-breaks-nfs-client-provisioner</id>
    <updated>2021-01-06T22:40:32.169Z</updated>
    <summary type="html">K3S version 1.20.0 breaks the nfs-subdir-external-provisioner with `unexpected error getting claim reference: selfLink was empty, can&apos;t make reference`</summary>
    <content type="html">&lt;p&gt;Kubernetes version 1.20.0 breaks the nfs-subdir-external-provisioner.&lt;/p&gt;
&lt;p&gt;The PersistentVolumeClaim stays in status “Pending”:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; k&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; pvc&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;NAME&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;         STATUS&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    VOLUME&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   CAPACITY&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   ACCESS&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; MODES&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   STORAGECLASS&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;          AGE&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;test-claim&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   Pending&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;                                      managed-nfs-storage&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;   10h&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The pod logs of client provisioner contains:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;unexpected error getting claim reference: selfLink was empty, can’t make reference&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; kubectl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; logs&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; nfs-client-provisioner&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;E0106&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; 06:18:07.328905&lt;/span&gt;&lt;span style=&quot;color:#D33682&quot;&gt;       1&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; controller.go:1004]&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; provision&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;default/test-claim&quot;&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;managed-nfs-storage&quot;:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; unexpected&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; error&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; getting&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; claim&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; reference:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; selfLink&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; was&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; empty,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; can&apos;t make reference&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;unexpected&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; error&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; getting&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; claim&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; reference:&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; selfLink&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; was&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; empty,&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; can&apos;t make reference&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The deprecation of selfLinks in Kubernetes 1.20.0 is responsible for this.&lt;/p&gt;
&lt;p&gt;As noted by &lt;a href=&quot;https://github.com/nealman13&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;nealman13&lt;/a&gt; in his &lt;a href=&quot;https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/issues/25#issuecomment-742616668&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;github comment&lt;/a&gt; setting the feature gate &lt;code&gt;RemoveSelfLink&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; is a workaround for this problem.&lt;/p&gt;
&lt;p&gt;But Rancher K3S doesn’t come with a &lt;code&gt;kube-apiserver.yaml&lt;/code&gt; file. But feature gates can be passed as commandline arguments directly to the service.&lt;/p&gt;
&lt;p&gt;For a fresh install of K3S the following commandline can be used:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; curl&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -sfL&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; https://get.k3s.io&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; sh&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; -s&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; --kube-apiserver-arg&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;feature-gates=RemoveSelfLink=false&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;An existing installation can be adjusted by changing the service directly:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; nano&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; /etc/systemd/system/k3s.service&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;ExecStart&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;/usr/local/bin/k3s&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;    server&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &apos;--kube-apiserver-arg&apos;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;        &apos;feature-gates=RemoveSelfLink=false&apos;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</content>
  </entry>
  <entry>
    <title type="html">Contributing to an opensource project</title>
    <link href="https://blog.loitzl.com/posts/contributing-to-an-opensource-project" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/contributing-to-an-opensource-project</id>
    <updated>2018-06-12T22:40:32.169Z</updated>
    <summary type="html">Only a few lines of code, but at the end I felt thrilled that I could contribute to the OfficeDevPnp project.</summary>
    <content type="html">&lt;p&gt;Only a few lines of code, but at the end I felt thrilled that I could contribute to the &lt;a href=&quot;https://github.com/pnp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;OfficeDevPnp&lt;/a&gt; project.&lt;/p&gt;
&lt;p&gt;The steps are quite simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fork the repo&lt;/li&gt;
&lt;li&gt;Create your local dev environment&lt;/li&gt;
&lt;li&gt;Implement your feature&lt;/li&gt;
&lt;li&gt;Read the &lt;a href=&quot;https://github.com/pnp/PnP-PowerShell/blob/master/CONTRIBUTING.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Contribution Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Fill out the &lt;a href=&quot;https://github.com/pnp/PnP-PowerShell/pull/1457&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;paperwork&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Open an &lt;a href=&quot;https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request-from-a-fork&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;upstream Pull Request&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;And probably get it merged&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/erwin-pr-3a3530c6/320.webp 320w, /generated/erwin-pr-3a3530c6/480.webp 480w, /generated/erwin-pr-3a3530c6/520.webp 520w&quot; sizes=&quot;(min-width: 520px) 520px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;get the PR merged&quot; src=&quot;/generated/erwin-pr-3a3530c6/520.png&quot; srcset=&quot;/generated/erwin-pr-3a3530c6/320.png 320w, /generated/erwin-pr-3a3530c6/480.png 480w, /generated/erwin-pr-3a3530c6/520.png 520w&quot; sizes=&quot;(min-width: 520px) 520px, 100vw&quot; width=&quot;520&quot; height=&quot;42&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;And the end you also get some kudos in the &lt;a href=&quot;https://developer.microsoft.com/en-us/office/blogs/sharepoint-development-community-pnp-may-2018-update/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;community blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/contributor-ref-3a3530c6/320.webp 320w, /generated/contributor-ref-3a3530c6/480.webp 480w, /generated/contributor-ref-3a3530c6/640.webp 640w, /generated/contributor-ref-3a3530c6/750.webp 750w, /generated/contributor-ref-3a3530c6/828.webp 828w, /generated/contributor-ref-3a3530c6/960.webp 960w, /generated/contributor-ref-3a3530c6/1210.webp 1210w&quot; sizes=&quot;(min-width: 1210px) 1210px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;get mentioned&quot; src=&quot;/generated/contributor-ref-3a3530c6/1210.png&quot; srcset=&quot;/generated/contributor-ref-3a3530c6/320.png 320w, /generated/contributor-ref-3a3530c6/480.png 480w, /generated/contributor-ref-3a3530c6/640.png 640w, /generated/contributor-ref-3a3530c6/750.png 750w, /generated/contributor-ref-3a3530c6/828.png 828w, /generated/contributor-ref-3a3530c6/960.png 960w, /generated/contributor-ref-3a3530c6/1210.png 1210w&quot; sizes=&quot;(min-width: 1210px) 1210px, 100vw&quot; width=&quot;1210&quot; height=&quot;879&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Thank you for your assistance and contributions on the behalf of the community. You are making a difference!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You’re welcome! 😁&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">Autofac and Automapper - A perfect match</title>
    <link href="https://blog.loitzl.com/posts/autofac-and-automapper-a-perfect-match" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/autofac-and-automapper-a-perfect-match</id>
    <updated>2017-03-11T22:40:32.169Z</updated>
    <summary type="html">With hexagonal and onion architectures, clean code, domain-driven-design, command query responsibility segragation Dependency Injection or Inversion of Control</summary>
    <content type="html">&lt;p&gt;&lt;img alt=&quot;Add List&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;533&quot; height=&quot;208&quot; src=&quot;/_astro/automapper%E2%9D%A4%EF%B8%8Fautofac.0TziotK7_Z1zWJ51.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;With hexagonal and onion architectures, clean code, domain-driven-design, command query responsibility segragation Dependency Injection or Inversion of Control comes in very handy.&lt;/p&gt;
&lt;p&gt;One thing I came across while working with &lt;a href=&quot;https://autofac.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Autofac&lt;/a&gt; and &lt;a href=&quot;http://automapper.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Automapper&lt;/a&gt; is, how good the play together.&lt;/p&gt;
&lt;p&gt;Imagine a basic setup where we handle an incoming request viewmodel, map it to an input command for a command handler, but the mapping is a little bit more complicated and we already want to use a service from the container during the mapping process. Automapper provides us with &lt;a href=&quot;https://docs.automapper.org/en/stable/Custom-type-converters.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;ITypeConverter&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://docs.automapper.org/en/stable/Custom-value-resolvers.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;code&gt;IValueResolver&lt;/code&gt;&lt;/a&gt; interfaces for more advanced mapping tasks.&lt;/p&gt;
&lt;p&gt;For a mapping like this&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; target &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; _mapper&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Map&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;TargetType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; SourceType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We could use the following SourceType to TargetType &lt;code&gt;TypeConverter&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; SourceToTargetTypeConverter&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;                    : &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;ITypeConverter&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;SourceType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;TargetType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; TargetType&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Convert&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;SourceType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; source, &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;TargetType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; destination, &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;ResolutionContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; context)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;        ..&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; targetObject&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It could be quite handy to have access to the Autofac container and request some &lt;code&gt;IFancyService&lt;/code&gt; inside our &lt;code&gt;SourceToTargetTypeConverter&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; SourceToTargetTypeConverter&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;                    : &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;ITypeConverter&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;SourceType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;TargetType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    private&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; readonly&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; IFancyService&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; _service;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; SourceToTargetTypeConverter&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IFancyService&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; service) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;        _service&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; service&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;  &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// require IFancyService from the container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; TargetType&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Convert&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;                  SourceType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; source, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;                  TargetType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; destination, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;                  ResolutionContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; context)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;        return&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; TargetType&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;            {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;                // use the service&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;                Thing&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; _service&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;GetAwesomeThing&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;() &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;            };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For this we first need to create a &lt;code&gt;MappingProfile&lt;/code&gt; that configures our &lt;code&gt;SourceToTargetTypeConverter&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; FancyProfile&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;AutoMapper&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Profile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;  public&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; FancyProfile&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    CreateMap&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;SourceType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;TargetType&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      .&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;ConvertUsing&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;SourceToTargetTypeConverter&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Later, when the container gets built we can use the assembly scanning feature of Autofac and register all &lt;code&gt;AutoMapper.Profile&lt;/code&gt; types auomatically.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;internal&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; class&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; MapperModule&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Autofac&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Module&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;  protected&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; override&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Load&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;ContainerBuilder&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; builder)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    builder&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;RegisterAssemblyTypes&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Assembly&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;GetExecutingAssembly&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;              .&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AssignableTo&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Profile&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;              .&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;As&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Profile&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;              .&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AutoActivate&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;    ..&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now comes the magic trick: everytime when a mapper is resolved, we need to resolve a &lt;code&gt;MapperConfiguration&lt;/code&gt; first. Because all &lt;code&gt;AutoMapper.Profile&lt;/code&gt; types have been already registered in the container before we are now able to get all &lt;code&gt;AutoMapper.Profile&lt;/code&gt; by resolving &lt;code&gt;context.Resolve&amp;#x3C;IEnumerable&amp;#x3C;Profile&gt;&gt;()&lt;/code&gt; - another nice feature of Autofac.&lt;/p&gt;
&lt;p&gt;When the actual Mapper is then created using the &lt;code&gt;config.CreateMapper(Func&amp;#x3C;Type, object&gt; serviceCtor)&lt;/code&gt; overload, Autofac will fulfill all dependencies defined in tha Automapper converters.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;  // Get all Profiles and add them to the MapperConfiguration&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  builder&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Register&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(context &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;      var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; profiles &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Resolve&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IEnumerable&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Profile&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;      var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; config &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; new&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; MapperConfiguration&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(x &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;        foreach&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; profile &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; profiles&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;        {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;          x&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AddProfile&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;profile&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;      return&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; config&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  }).&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;SingleInstance&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AutoActivate&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;AsSelf&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;  // Resolve the MapperConfiguration and call CreateMapper()  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  builder&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Register&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(context &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; ctx &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; context&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Resolve&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;IComponentContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;    var&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; config &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; ctx&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Resolve&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;MapperConfiguration&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; config&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;CreateMapper&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;      t &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&gt;&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; ctx&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Resolve&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;// The magic is happening here: Autofac will now fulfill all dependcies defined in MapperConfigurations&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  });&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Works pretty nice that way and it perfectly fits into an hexagonal or onion architecture.&lt;/p&gt;
&lt;p&gt;Btw, thanks Mario for pointing me to this idea 😘&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2021&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New automapper version&lt;/li&gt;
&lt;li&gt;Find the updated code in the &lt;a href=&quot;https://github.com/mloitzl/AutofacAndAutomapper&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Github repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>
  </entry>
  <entry>
    <title type="html">Office 365 Junk Mail default setting</title>
    <link href="https://blog.loitzl.com/posts/office-365-junk-mail-default-setting" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/office-365-junk-mail-default-setting</id>
    <updated>2014-08-06T22:40:32.169Z</updated>
    <summary type="html">Office 365 keeps filtering mail from recipients off my contact list in the “Junk E-Mail” folder which is quite annoying</summary>
    <content type="html">&lt;p&gt;Office 365 keeps filtering mail from recipients off my contact list in the “Junk E-Mail” folder which is quite annoying.&lt;/p&gt;
&lt;p&gt;This behaviour can be changed via the “Settings &gt; Options &gt; Block or Allow”. By default “Trust email from my contacts” is turned off which is not the best choice for this setting.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">SharePoint 2013 Composite Handbook</title>
    <link href="https://blog.loitzl.com/posts/sharepoint-2013-composite-handbook" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/sharepoint-2013-composite-handbook</id>
    <updated>2013-02-18T22:40:32.169Z</updated>
    <summary type="html">For people like me who strive to use SharePoint 2013 oob features in their solutions...</summary>
    <content type="html">&lt;p&gt;For people like me who strive to use SharePoint 2013 oob features in their solutions, the SharePoint 2013 Composites Handbook is available for download here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.microsoft.com/en-us/download/details.aspx?id=36055&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SharePoint 2013 Composites Handbook&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">Load and Execute for the SharePoint Client Object Model</title>
    <link href="https://blog.loitzl.com/posts/load-and-execute-for-the-sharepoint-20102013-client-object-model" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/load-and-execute-for-the-sharepoint-20102013-client-object-model</id>
    <updated>2013-02-11T22:40:32.169Z</updated>
    <summary type="html">Save on line of code in CSOM</summary>
    <content type="html">&lt;p&gt;Since I am very lazy programmer I always think about shortening things a little bit.&lt;/p&gt;
&lt;p&gt;Instead of writing…&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Microsoft&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;SharePoint&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Client&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Web&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; appWeb &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; siteContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Web&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;siteContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Load&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;appWeb&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;siteContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;ExecuteQuery&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;… its worth having a look on the signature of the &lt;code&gt;Load&lt;/code&gt; method:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Load&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; clientObject, &lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; Expression&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Func&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;&gt;[] retrievals) &lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;where&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;ClientObject&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It turns out that I can save one line of code every time by declaring an extension method like…&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt; static&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; LoadAndExecute&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;  this&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; Microsoft&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;SharePoint&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Client&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;ClientContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; me,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;  T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; clientObject,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;  params&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; System&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Linq&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Expressions&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Expression&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Func&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;&gt;&gt;[] retrievals) &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;         where&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; : &lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Microsoft&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;SharePoint&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Client&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;ClientObject&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    me&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Load&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;clientObject&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;retrievals&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    me&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;ExecuteQuery&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which simplifies the above code to:&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Microsoft&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;SharePoint&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Client&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#CB4B16&quot;&gt;Web&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; appWeb &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; siteContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Web&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;siteContext&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;LoadAndExecute&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;appWeb&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One line saved…&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">Create a SharePoint 2013 Workflow with a custom Initiation Form in Visual Studio 2012</title>
    <link href="https://blog.loitzl.com/posts/create-a-sharepoint-2013-workflow-with-a-custom-initiation-form-in-visual-studio-2012" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/create-a-sharepoint-2013-workflow-with-a-custom-initiation-form-in-visual-studio-2012</id>
    <updated>2013-02-07T22:40:32.169Z</updated>
    <summary type="html"></summary>
    <content type="html">&lt;h1 id=&quot;prerequisites&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;prerequisites&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#prerequisites&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Prerequisites&lt;/h1&gt;
&lt;p&gt;Create a on-prem high trust app as described in my previous blog post.&lt;/p&gt;
&lt;h1 id=&quot;add-the-workflow&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;add the workflow&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#add-the-workflow&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Add the Workflow&lt;/h1&gt;
&lt;p&gt;First of all we need to add a list to host the workflow by adding a new item of type “List” to the SharePoint AppWeb project.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/1-Add-List-4fe25da9/320.webp 320w, /generated/1-Add-List-4fe25da9/480.webp 480w, /generated/1-Add-List-4fe25da9/640.webp 640w, /generated/1-Add-List-4fe25da9/750.webp 750w, /generated/1-Add-List-4fe25da9/828.webp 828w, /generated/1-Add-List-4fe25da9/960.webp 960w, /generated/1-Add-List-4fe25da9/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Add List&quot; src=&quot;/generated/1-Add-List-4fe25da9/1239.png&quot; srcset=&quot;/generated/1-Add-List-4fe25da9/320.png 320w, /generated/1-Add-List-4fe25da9/480.png 480w, /generated/1-Add-List-4fe25da9/640.png 640w, /generated/1-Add-List-4fe25da9/750.png 750w, /generated/1-Add-List-4fe25da9/828.png 828w, /generated/1-Add-List-4fe25da9/960.png 960w, /generated/1-Add-List-4fe25da9/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;In a further step, the list could be configured using the new list designer in Visual Studio 2012.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/2-Add-List-Designer-4fe25da9/320.webp 320w, /generated/2-Add-List-Designer-4fe25da9/480.webp 480w, /generated/2-Add-List-Designer-4fe25da9/640.webp 640w, /generated/2-Add-List-Designer-4fe25da9/750.webp 750w, /generated/2-Add-List-Designer-4fe25da9/828.webp 828w, /generated/2-Add-List-Designer-4fe25da9/960.webp 960w, /generated/2-Add-List-Designer-4fe25da9/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Add List Designer&quot; src=&quot;/generated/2-Add-List-Designer-4fe25da9/1239.png&quot; srcset=&quot;/generated/2-Add-List-Designer-4fe25da9/320.png 320w, /generated/2-Add-List-Designer-4fe25da9/480.png 480w, /generated/2-Add-List-Designer-4fe25da9/640.png 640w, /generated/2-Add-List-Designer-4fe25da9/750.png 750w, /generated/2-Add-List-Designer-4fe25da9/828.png 828w, /generated/2-Add-List-Designer-4fe25da9/960.png 960w, /generated/2-Add-List-Designer-4fe25da9/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Now that we have a list, we can add a workflow to be run on that list by adding a new Item of type “Workflow”to the SharePoint AppWeb project. Set the workflow to start manually and associate it with the previously created list. Select the according items to create a Workflow History And Workflow Tasks List for the Workflow.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/3-AddWorkflow-Set-Lists-4fe25da9/320.webp 320w, /generated/3-AddWorkflow-Set-Lists-4fe25da9/480.webp 480w, /generated/3-AddWorkflow-Set-Lists-4fe25da9/640.webp 640w, /generated/3-AddWorkflow-Set-Lists-4fe25da9/750.webp 750w, /generated/3-AddWorkflow-Set-Lists-4fe25da9/828.webp 828w, /generated/3-AddWorkflow-Set-Lists-4fe25da9/960.webp 960w, /generated/3-AddWorkflow-Set-Lists-4fe25da9/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Add Workflow - Set Lists&quot; src=&quot;/generated/3-AddWorkflow-Set-Lists-4fe25da9/1239.png&quot; srcset=&quot;/generated/3-AddWorkflow-Set-Lists-4fe25da9/320.png 320w, /generated/3-AddWorkflow-Set-Lists-4fe25da9/480.png 480w, /generated/3-AddWorkflow-Set-Lists-4fe25da9/640.png 640w, /generated/3-AddWorkflow-Set-Lists-4fe25da9/750.png 750w, /generated/3-AddWorkflow-Set-Lists-4fe25da9/828.png 828w, /generated/3-AddWorkflow-Set-Lists-4fe25da9/960.png 960w, /generated/3-AddWorkflow-Set-Lists-4fe25da9/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;The new Workflow Designer should now be visible showing a workflow with an empty sequence.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/4-WorkflowDesigner-4fe25da9/320.webp 320w, /generated/4-WorkflowDesigner-4fe25da9/480.webp 480w, /generated/4-WorkflowDesigner-4fe25da9/640.webp 640w, /generated/4-WorkflowDesigner-4fe25da9/750.webp 750w, /generated/4-WorkflowDesigner-4fe25da9/828.webp 828w, /generated/4-WorkflowDesigner-4fe25da9/960.webp 960w, /generated/4-WorkflowDesigner-4fe25da9/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Workflow Designer&quot; src=&quot;/generated/4-WorkflowDesigner-4fe25da9/1239.png&quot; srcset=&quot;/generated/4-WorkflowDesigner-4fe25da9/320.png 320w, /generated/4-WorkflowDesigner-4fe25da9/480.png 480w, /generated/4-WorkflowDesigner-4fe25da9/640.png 640w, /generated/4-WorkflowDesigner-4fe25da9/750.png 750w, /generated/4-WorkflowDesigner-4fe25da9/828.png 828w, /generated/4-WorkflowDesigner-4fe25da9/960.png 960w, /generated/4-WorkflowDesigner-4fe25da9/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;The custom initiation form will just contain a single string. In order to use that string within the workflow a variable has to be added as input parameter, e.g. “inputString”. To show that the value is actually submitted to the workflow we use a “WriteToLog” Activity that writes the value of our input parameter to the Workflow History List.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/320.webp 320w, /generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/480.webp 480w, /generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/640.webp 640w, /generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/750.webp 750w, /generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/828.webp 828w, /generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/960.webp 960w, /generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Use Input Parameter in Activity&quot; src=&quot;/generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/1239.png&quot; srcset=&quot;/generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/320.png 320w, /generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/480.png 480w, /generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/640.png 640w, /generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/750.png 750w, /generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/828.png 828w, /generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/960.png 960w, /generated/5-WorkflowDesigner-Use-Input-Parameter-in-Activity1-4fe25da9/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;The next step is to add a custom Initiation Form by adding a new Item of Type “InitiatonForm” to the Workflow element. This adds a default InitiationForm to the project which is already populated with some code.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/6-Add-Initiation-Form-Code-4fe25da9/320.webp 320w, /generated/6-Add-Initiation-Form-Code-4fe25da9/480.webp 480w, /generated/6-Add-Initiation-Form-Code-4fe25da9/640.webp 640w, /generated/6-Add-Initiation-Form-Code-4fe25da9/750.webp 750w, /generated/6-Add-Initiation-Form-Code-4fe25da9/828.webp 828w, /generated/6-Add-Initiation-Form-Code-4fe25da9/960.webp 960w, /generated/6-Add-Initiation-Form-Code-4fe25da9/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Add Initiation Form&quot; src=&quot;/generated/6-Add-Initiation-Form-Code-4fe25da9/1239.png&quot; srcset=&quot;/generated/6-Add-Initiation-Form-Code-4fe25da9/320.png 320w, /generated/6-Add-Initiation-Form-Code-4fe25da9/480.png 480w, /generated/6-Add-Initiation-Form-Code-4fe25da9/640.png 640w, /generated/6-Add-Initiation-Form-Code-4fe25da9/750.png 750w, /generated/6-Add-Initiation-Form-Code-4fe25da9/828.png 828w, /generated/6-Add-Initiation-Form-Code-4fe25da9/960.png 960w, /generated/6-Add-Initiation-Form-Code-4fe25da9/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Clean up the form to only contain a single text field for our string input variable. In the “startWorkflow” function triggered by the submit button the value of the text field must be added to the params object. It is also necessary to get the List Item ID from the URL, since this is needed as parameter for the “startWorkflowOnListItem” method on the “WorkflowInstance” object.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/7-Add-Initiation-Form-Code-changed-4fe25da9/320.webp 320w, /generated/7-Add-Initiation-Form-Code-changed-4fe25da9/480.webp 480w, /generated/7-Add-Initiation-Form-Code-changed-4fe25da9/640.webp 640w, /generated/7-Add-Initiation-Form-Code-changed-4fe25da9/750.webp 750w, /generated/7-Add-Initiation-Form-Code-changed-4fe25da9/828.webp 828w, /generated/7-Add-Initiation-Form-Code-changed-4fe25da9/960.webp 960w, /generated/7-Add-Initiation-Form-Code-changed-4fe25da9/1241.webp 1241w&quot; sizes=&quot;(min-width: 1241px) 1241px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Changed Initiation Form&quot; src=&quot;/generated/7-Add-Initiation-Form-Code-changed-4fe25da9/1241.png&quot; srcset=&quot;/generated/7-Add-Initiation-Form-Code-changed-4fe25da9/320.png 320w, /generated/7-Add-Initiation-Form-Code-changed-4fe25da9/480.png 480w, /generated/7-Add-Initiation-Form-Code-changed-4fe25da9/640.png 640w, /generated/7-Add-Initiation-Form-Code-changed-4fe25da9/750.png 750w, /generated/7-Add-Initiation-Form-Code-changed-4fe25da9/828.png 828w, /generated/7-Add-Initiation-Form-Code-changed-4fe25da9/960.png 960w, /generated/7-Add-Initiation-Form-Code-changed-4fe25da9/1241.png 1241w&quot; sizes=&quot;(min-width: 1241px) 1241px, 100vw&quot; width=&quot;1241&quot; height=&quot;1005&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;The last step is to add a reference to the custom initiation form in the Elements deklaration of the workflow element.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/320.webp 320w, /generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/480.webp 480w, /generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/640.webp 640w, /generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/750.webp 750w, /generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/828.webp 828w, /generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/960.webp 960w, /generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Initiation Form Elements Declaration&quot; src=&quot;/generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/1239.png&quot; srcset=&quot;/generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/320.png 320w, /generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/480.png 480w, /generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/640.png 640w, /generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/750.png 750w, /generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/828.png 828w, /generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/960.png 960w, /generated/8-Add-Initiation-Form-Elements-Deklaration-4fe25da9/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;The interesting part here is, that the URL Token replacement does not seem to work properly here as I posted in Apps for SharePoint &lt;a href=&quot;https://social.msdn.microsoft.com/Forums/en-US/d23338c8-255e-4945-8a13-8bcdf0d6e167/2013-workflow-initiation-form-in-remoteappurl?forum=appsforsharepoint&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MSDN forum&lt;/a&gt;. This means that custom initiation and association forms can only be created in the AppWeb and not in the Remote App, which makes more complicated scenarios pretty much bound to javascript/html implementations for now.&lt;/p&gt;
&lt;p&gt;After a deploy the ListItem has a workflow associated to it and after starting it manually, the user gets our custom initiation form presented.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/9-Run-the-Workflow-The-Form-4fe25da9/320.webp 320w, /generated/9-Run-the-Workflow-The-Form-4fe25da9/480.webp 480w, /generated/9-Run-the-Workflow-The-Form-4fe25da9/640.webp 640w, /generated/9-Run-the-Workflow-The-Form-4fe25da9/750.webp 750w, /generated/9-Run-the-Workflow-The-Form-4fe25da9/828.webp 828w, /generated/9-Run-the-Workflow-The-Form-4fe25da9/960.webp 960w, /generated/9-Run-the-Workflow-The-Form-4fe25da9/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Workflow Form&quot; src=&quot;/generated/9-Run-the-Workflow-The-Form-4fe25da9/1239.png&quot; srcset=&quot;/generated/9-Run-the-Workflow-The-Form-4fe25da9/320.png 320w, /generated/9-Run-the-Workflow-The-Form-4fe25da9/480.png 480w, /generated/9-Run-the-Workflow-The-Form-4fe25da9/640.png 640w, /generated/9-Run-the-Workflow-The-Form-4fe25da9/750.png 750w, /generated/9-Run-the-Workflow-The-Form-4fe25da9/828.png 828w, /generated/9-Run-the-Workflow-The-Form-4fe25da9/960.png 960w, /generated/9-Run-the-Workflow-The-Form-4fe25da9/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;After the workflow is completed, the workflow history log shows the value entered in  the initiation form.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/10-Run-the-Workflow-Result-4fe25da9/320.webp 320w, /generated/10-Run-the-Workflow-Result-4fe25da9/480.webp 480w, /generated/10-Run-the-Workflow-Result-4fe25da9/640.webp 640w, /generated/10-Run-the-Workflow-Result-4fe25da9/750.webp 750w, /generated/10-Run-the-Workflow-Result-4fe25da9/828.webp 828w, /generated/10-Run-the-Workflow-Result-4fe25da9/960.webp 960w, /generated/10-Run-the-Workflow-Result-4fe25da9/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Workflow Result&quot; src=&quot;/generated/10-Run-the-Workflow-Result-4fe25da9/1239.png&quot; srcset=&quot;/generated/10-Run-the-Workflow-Result-4fe25da9/320.png 320w, /generated/10-Run-the-Workflow-Result-4fe25da9/480.png 480w, /generated/10-Run-the-Workflow-Result-4fe25da9/640.png 640w, /generated/10-Run-the-Workflow-Result-4fe25da9/750.png 750w, /generated/10-Run-the-Workflow-Result-4fe25da9/828.png 828w, /generated/10-Run-the-Workflow-Result-4fe25da9/960.png 960w, /generated/10-Run-the-Workflow-Result-4fe25da9/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://social.msdn.microsoft.com/Forums/en-US/d23338c8-255e-4945-8a13-8bcdf0d6e167/2013-workflow-initiation-form-in-remoteappurl?forum=appsforsharepoint&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2013 Workflow Initiation Form in ~remoteAppUrl&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">Creating a SharePoint 2013 Provider Hosted on-prem App</title>
    <link href="https://blog.loitzl.com/posts/creating-a-sharepoint-2013-provider-hosted-on-prem-app" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/creating-a-sharepoint-2013-provider-hosted-on-prem-app</id>
    <updated>2013-02-07T22:40:32.169Z</updated>
    <summary type="html"></summary>
    <content type="html">&lt;h1 id=&quot;prerequisites&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;prerequisites&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#prerequisites&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Prerequisites&lt;/h1&gt;
&lt;p&gt;First of all a on-prem development environment has to be created. I used the &lt;a href=&quot;https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/set-up-an-on-premises-development-environment-for-sharepoint-add-ins?redirectedfrom=MSDN&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;How to: Set up an on-premises development environment for apps for SharePoint&lt;/a&gt; found in MSDN.&lt;/p&gt;
&lt;h1 id=&quot;high-trust-app&quot; style=&quot;position: relative;&quot;&gt;&lt;a aria-label=&quot;Link to heading &amp;#x22;high trust app&amp;#x22;&quot; class=&quot;anchor before&quot; href=&quot;#high-trust-app&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; fill=&quot;none&quot; focusable=&quot;false&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot;&gt;&lt;path d=&quot;M9.14339 10.691L9.35031 10.4841C11.329 8.50532 14.5372 8.50532 16.5159 10.4841C18.4947 12.4628 18.4947 15.671 16.5159 17.6497L13.6497 20.5159C11.671 22.4947 8.46279 22.4947 6.48405 20.5159C4.50532 18.5372 4.50532 15.329 6.48405 13.3503L6.9484 12.886&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M17.0516 11.114L17.5159 10.6497C19.4947 8.67095 19.4947 5.46279 17.5159 3.48405C15.5372 1.50532 12.329 1.50532 10.3503 3.48405L7.48405 6.35031C5.50532 8.32904 5.50532 11.5372 7.48405 13.5159C9.46279 15.4947 12.671 15.4947 14.6497 13.5159L14.8566 13.309&quot; stroke=&quot;currentColor&quot; stroke-linecap=&quot;round&quot; stroke-width=&quot;1.5&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;High Trust App&lt;/h1&gt;
&lt;p&gt;In order to create an on-prem app, the app must be registered in SharePoint as “trusted token issuer”. There are currently two different procedures depending on the version of Office Developer Tools for Visual Studio 2012. The respective procedures by using self-signed certificates is described in &lt;a href=&quot;https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/create-high-trust-sharepoint-add-ins?redirectedfrom=MSDN&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;How to: Create high-trust apps for SharePoint 2013 using the server-to-server protocol (advanced topic)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I am using Active Directory Certificate services my development environment, so I am able to create certificate with my own trusted Root Authority in the IIS configuration UI by clicking “Create Domain Certificate”.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/1-Create-Domain-Certificate-c7dbc2b8/320.webp 320w, /generated/1-Create-Domain-Certificate-c7dbc2b8/480.webp 480w, /generated/1-Create-Domain-Certificate-c7dbc2b8/640.webp 640w, /generated/1-Create-Domain-Certificate-c7dbc2b8/750.webp 750w, /generated/1-Create-Domain-Certificate-c7dbc2b8/828.webp 828w, /generated/1-Create-Domain-Certificate-c7dbc2b8/960.webp 960w, /generated/1-Create-Domain-Certificate-c7dbc2b8/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Create Domain Certificate&quot; src=&quot;/generated/1-Create-Domain-Certificate-c7dbc2b8/1239.png&quot; srcset=&quot;/generated/1-Create-Domain-Certificate-c7dbc2b8/320.png 320w, /generated/1-Create-Domain-Certificate-c7dbc2b8/480.png 480w, /generated/1-Create-Domain-Certificate-c7dbc2b8/640.png 640w, /generated/1-Create-Domain-Certificate-c7dbc2b8/750.png 750w, /generated/1-Create-Domain-Certificate-c7dbc2b8/828.png 828w, /generated/1-Create-Domain-Certificate-c7dbc2b8/960.png 960w, /generated/1-Create-Domain-Certificate-c7dbc2b8/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;After creating the certificate, both the public (.cer) and the private (.pfx) key have to be exported. The .cer file is exported by opening the certificate and hitting “Copy to file” on the “Details” tab. Use the default settings in the dialog.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/320.webp 320w, /generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/480.webp 480w, /generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/640.webp 640w, /generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/750.webp 750w, /generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/828.webp 828w, /generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/960.webp 960w, /generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;New Domain Certificate&quot; src=&quot;/generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/1239.png&quot; srcset=&quot;/generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/320.png 320w, /generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/480.png 480w, /generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/640.png 640w, /generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/750.png 750w, /generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/828.png 828w, /generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/960.png 960w, /generated/2-NewDomainCertificate-export-cer-2-c7dbc2b8/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;The .pfx file can be exported by clicking the “Export” in the Actions sidebar. Don’t forget to set a password, since it is needed later when creating the Visual Studio project.&lt;/p&gt;
&lt;p&gt;The next step is to register the App as trusted token issuer, I streamlined this process in a &lt;a href=&quot;add-new-trusted-token-issuer-to-a-sharepoint-2013-site-s2s-hightrust-apps&quot;&gt;PowerShell&lt;/a&gt; script for the Preview 2 Version of the Office Developer Tools for Visual Studio 2012. The first parameter of the script denotes the site, where the app will be deployed to and the second parameter points to the public key (.cer) file.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/4-AddTrustedTokenIssuer-c7dbc2b8/320.webp 320w, /generated/4-AddTrustedTokenIssuer-c7dbc2b8/480.webp 480w, /generated/4-AddTrustedTokenIssuer-c7dbc2b8/640.webp 640w, /generated/4-AddTrustedTokenIssuer-c7dbc2b8/750.webp 750w, /generated/4-AddTrustedTokenIssuer-c7dbc2b8/828.webp 828w, /generated/4-AddTrustedTokenIssuer-c7dbc2b8/960.webp 960w, /generated/4-AddTrustedTokenIssuer-c7dbc2b8/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;Add Trusted Token Issuer&quot; src=&quot;/generated/4-AddTrustedTokenIssuer-c7dbc2b8/1239.png&quot; srcset=&quot;/generated/4-AddTrustedTokenIssuer-c7dbc2b8/320.png 320w, /generated/4-AddTrustedTokenIssuer-c7dbc2b8/480.png 480w, /generated/4-AddTrustedTokenIssuer-c7dbc2b8/640.png 640w, /generated/4-AddTrustedTokenIssuer-c7dbc2b8/750.png 750w, /generated/4-AddTrustedTokenIssuer-c7dbc2b8/828.png 828w, /generated/4-AddTrustedTokenIssuer-c7dbc2b8/960.png 960w, /generated/4-AddTrustedTokenIssuer-c7dbc2b8/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;The result shows a new IssuerID which is used to identify the app. The IssuerID has to be entered when creating the Visual Studio Project.&lt;/p&gt;
&lt;p&gt;After creating a new App for SharePoint 2013 Project, select Provider-Hosted as hosting option. Enter a name and the site url used before and hit next.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/5-New-App-ProviderHosted-c7dbc2b8/320.webp 320w, /generated/5-New-App-ProviderHosted-c7dbc2b8/480.webp 480w, /generated/5-New-App-ProviderHosted-c7dbc2b8/640.webp 640w, /generated/5-New-App-ProviderHosted-c7dbc2b8/750.webp 750w, /generated/5-New-App-ProviderHosted-c7dbc2b8/828.webp 828w, /generated/5-New-App-ProviderHosted-c7dbc2b8/960.webp 960w, /generated/5-New-App-ProviderHosted-c7dbc2b8/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;New ProviderHosted App&quot; src=&quot;/generated/5-New-App-ProviderHosted-c7dbc2b8/1239.png&quot; srcset=&quot;/generated/5-New-App-ProviderHosted-c7dbc2b8/320.png 320w, /generated/5-New-App-ProviderHosted-c7dbc2b8/480.png 480w, /generated/5-New-App-ProviderHosted-c7dbc2b8/640.png 640w, /generated/5-New-App-ProviderHosted-c7dbc2b8/750.png 750w, /generated/5-New-App-ProviderHosted-c7dbc2b8/828.png 828w, /generated/5-New-App-ProviderHosted-c7dbc2b8/960.png 960w, /generated/5-New-App-ProviderHosted-c7dbc2b8/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Select “Use a certificate” for authentication and select the private key (.pfx) file, enter the IssuerID created by the PowerShell script before and the password for the private key file.&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/6-New-App-Use-Certificate-c7dbc2b8/320.webp 320w, /generated/6-New-App-Use-Certificate-c7dbc2b8/480.webp 480w, /generated/6-New-App-Use-Certificate-c7dbc2b8/640.webp 640w, /generated/6-New-App-Use-Certificate-c7dbc2b8/750.webp 750w, /generated/6-New-App-Use-Certificate-c7dbc2b8/828.webp 828w, /generated/6-New-App-Use-Certificate-c7dbc2b8/960.webp 960w, /generated/6-New-App-Use-Certificate-c7dbc2b8/1239.webp 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;New App Use Certificate&quot; src=&quot;/generated/6-New-App-Use-Certificate-c7dbc2b8/1239.png&quot; srcset=&quot;/generated/6-New-App-Use-Certificate-c7dbc2b8/320.png 320w, /generated/6-New-App-Use-Certificate-c7dbc2b8/480.png 480w, /generated/6-New-App-Use-Certificate-c7dbc2b8/640.png 640w, /generated/6-New-App-Use-Certificate-c7dbc2b8/750.png 750w, /generated/6-New-App-Use-Certificate-c7dbc2b8/828.png 828w, /generated/6-New-App-Use-Certificate-c7dbc2b8/960.png 960w, /generated/6-New-App-Use-Certificate-c7dbc2b8/1239.png 1239w&quot; sizes=&quot;(min-width: 1239px) 1239px, 100vw&quot; width=&quot;1239&quot; height=&quot;998&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;
&lt;p&gt;Hit F5 if you get a page showing the Title of the HostWeb everythings OK 🙂&lt;/p&gt;
&lt;p&gt;&lt;picture&gt;&lt;source srcset=&quot;/generated/7-New-App-Result-c7dbc2b8/320.webp 320w, /generated/7-New-App-Result-c7dbc2b8/480.webp 480w, /generated/7-New-App-Result-c7dbc2b8/640.webp 640w, /generated/7-New-App-Result-c7dbc2b8/750.webp 750w, /generated/7-New-App-Result-c7dbc2b8/828.webp 828w, /generated/7-New-App-Result-c7dbc2b8/899.webp 899w&quot; sizes=&quot;(min-width: 899px) 899px, 100vw&quot; type=&quot;image/webp&quot;&gt;&lt;img alt=&quot;New App is running&quot; src=&quot;/generated/7-New-App-Result-c7dbc2b8/899.png&quot; srcset=&quot;/generated/7-New-App-Result-c7dbc2b8/320.png 320w, /generated/7-New-App-Result-c7dbc2b8/480.png 480w, /generated/7-New-App-Result-c7dbc2b8/640.png 640w, /generated/7-New-App-Result-c7dbc2b8/750.png 750w, /generated/7-New-App-Result-c7dbc2b8/828.png 828w, /generated/7-New-App-Result-c7dbc2b8/899.png 899w&quot; sizes=&quot;(min-width: 899px) 899px, 100vw&quot; width=&quot;899&quot; height=&quot;321&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/picture&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">Add new Trusted Token Issuer to a SharePoint 2013 Site – S2S HighTrust Apps</title>
    <link href="https://blog.loitzl.com/posts/add-new-trusted-token-issuer-to-a-sharepoint-2013-site-s2s-hightrust-apps" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/add-new-trusted-token-issuer-to-a-sharepoint-2013-site-s2s-hightrust-apps</id>
    <updated>2012-12-18T22:40:32.169Z</updated>
    <summary type="html"></summary>
    <content type="html">&lt;p&gt;For SharePoint 2013 App Development on-premise, there might not be a Cloud ACS around to get the token stuff done. For this case the App must create its own access tokens and SharePoint 2013 must know about them as Trusted Security Token Issuers. The App creates a token (with the users credentials) and signs it with its own private key. If the SharePoint 2013 Site hosting the app knows about the IssuerID, the Server can extract the token and grant access.&lt;/p&gt;
&lt;p&gt;The whole process is described in &lt;a href=&quot;https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/create-high-trust-sharepoint-add-ins?redirectedfrom=MSDN&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;How to: Create high-trust apps for SharePoint 2013 using the server-to-server protocol (advanced topic)&lt;/a&gt;. Note that there is a difference between SharePoint Developer Tools Preview and Preview 2.&lt;/p&gt;
&lt;p&gt;Based on &lt;a href=&quot;https://www.andrewconnell.com/blog/Registering-SP2013-High-Trust-Apps-Using-S2S-the-Easy-Way/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Andrew Connell’s&lt;/a&gt; Script for the Beta and RTM Version, I composed a little powershell script that streamlines the registration, since this has to be done for every App. All that is needed is a developer site and a private certificate.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; The flag –IsTrustBroker in New-SPTrustedSecurityTokenIssuer makes the certificate reusable. So several apps can share the same certificate ussing the same issuer ID. &lt;a href=&quot;https://docs.microsoft.com/en-us/archive/blogs/speschka/more-troubleshooting-tips-for-high-trust-apps-on-sharepoint-2013&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[0]&lt;/a&gt; – Bullet: Token issuer not configured as trust broker.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# ———————————————————————————&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# Setup for a new Trusted Security Token Issuer for an on-prem Developer Hosted App&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# $TargetUrl = Developer SiteCollection Url&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# $publicCertPath = Path to the public part of the certificate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# (optional) $issuerID = Unique ID for the App, generated if omitted&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# e.g. .\AddTrustedTokenIssuerToSite “http://developerSite/” “c:\PathTo.Cer”&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# The isserID is printed at the end of the script -&gt; keep it for&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# the App’s web.config&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# ———————————————————————————&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;param&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;TargetUrl&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;publicCertPath&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;issuerID&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “”&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “Register new Trusted Identity Token Issuer…”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” Script Steps:”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” (1 of 5) Validating parameters…”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” (2 of 5) Verify SharePoint PowerShell Snapin Loaded”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” (3 of 5) Check if site collection exists at target &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;SiteUrl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” (4 of 5) Adding IssuerIdentifier at target &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;SiteUrl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” (5 of 5) Verify OAuth over https is disabled”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# ———————————————–&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# verify parameters passed in&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “(1 of 5) Validating parameters…”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;TargetUrl&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -eq&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#B58900&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -xor&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;TargetUrl&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -eq&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “”&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  Write-Error&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ‘$TargetUrl is required’&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  Exit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;publicCertPath&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -eq&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#B58900&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -xor&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;publicCertPath&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -eq&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “”&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  Write-Error&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ‘$publicCertPath is required’&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  Exit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” All parameters valid”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor Gray&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# ———————————————–&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;issuerID&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -eq&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#B58900&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -xor&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;issuerID&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -eq&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “”&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ‘ IssuerID is empty, generating’&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;issuerID&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;System.Guid&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]::NewGuid().ToString()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# ———————————————–&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# Load SharePoint PowerShell snapin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “(2 of 5) Verify SharePoint PowerShell Snapin Loaded”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;snapin&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Get-PSSnapin&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Where-Object&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;.Name&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -eq&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ‘Microsoft.SharePoint.PowerShell’&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;snapin&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -eq&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#B58900&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” .. loading SharePoint PowerShell Snapin…”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor Gray&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  Add-PSSnapin&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “Microsoft.SharePoint.PowerShell”&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” Microsoft SharePoint PowerShell snapin loaded”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor Gray&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;# ———————————————–&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “(3 of 5) Check if site collection exists at target &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;TargetUrl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;targetSpSite&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Get-SPSite&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;TargetUrl&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;targetSpSite&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -ne&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#B58900&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” … site found”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor Gray&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;realm&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Get-SPAuthenticationRealm&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ServiceContext &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;targetSpSite&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;certificate&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Get-PfxCertificate&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;publicCertPath&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;fullIssuerIdentifier&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;issuerId&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ‘@’&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;realm&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  Write-Host&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “(4 of 5) Adding IssuerIdentifier &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;fullIssuerIdentifier&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” as TrustedSecurityTokenIssuer to &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;TargetUrl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; New-SPTrustedSecurityTokenIssuer&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Name &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;issuerId&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;Certificate &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;certificate&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;RegisteredIssuerName &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;fullIssuerIdentifier&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; –IsTrustBroker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  Write-Host&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  write-host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “— ### Results ### —”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor Green&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  write-host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” Realm: &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;realm&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor Green&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#93A1A1;font-style:italic&quot;&gt;  # write-host “FullIssuerID: $fullIssuerIdentifier” -ForegroundColor Green&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  write-host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” IssuerID: &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;issuerId&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor Green&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  write-host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ” Result: &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor Green&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  write-host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “— ### Results ### —”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor Green&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  Write-Error&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;TargetUrl&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; not found”&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  Exit&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;Write-Host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; “(5 of 5) Verify OAuth over https is disabled”&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;serviceConfig&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt; Get-SPSecurityTokenServiceConfig&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;serviceConfig.AllowOAuthOverHttp&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -ne&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#B58900&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;    $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;serviceConfig.AllowOAuthOverHttp&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#B58900&quot;&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;    $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;serviceConfig.Update&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;    write-host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ‘ OAuth over https disabled’&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor Green&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  write-host&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; ‘ OAuth over https is already disabled’&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;ForegroundColor White&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;0: &lt;a href=&quot;https://docs.microsoft.com/en-us/archive/blogs/speschka/more-troubleshooting-tips-for-high-trust-apps-on-sharepoint-2013&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;More TroubleShooting Tips for High Trust Apps on SharePoint 2013&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
  <entry>
    <title type="html">Export Farm Solution wsp Files SharePoint 2007 and 2010</title>
    <link href="https://blog.loitzl.com/posts/export-farm-solution-wsp-files-sharepoint-2007-und-2010" rel="alternate" type="text/html"/>
    <id>https://blog.loitzl.com/posts/export-farm-solution-wsp-files-sharepoint-2007-und-2010</id>
    <updated>2012-06-04T22:40:32.169Z</updated>
    <summary type="html">Exports all SharePoint Farm Solution Packages (.wsp) from the farm solution store</summary>
    <content type="html">&lt;p&gt;The following PowerShell Snippet exports all SharePoint Farm Solution Packages (.wsp) from the farm solution store. It does work on Windows 2003 R2 with PowerShell 1.0, which I find very practical because it is the standard configuration for WSS3 and MOSS 2007 installations.&lt;/p&gt;
&lt;pre class=&quot;astro-code solarized-light&quot; style=&quot;background-color:#FDF6E3;color:#657B83; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;powershell&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;System.Reflection.Assembly&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]::LoadWithPartialName(&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;Microsoft.SharePoint&quot;&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;farm&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#586E75;font-weight:bold&quot;&gt;Microsoft.SharePoint.Administration.SPFarm&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;]::Local&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;farm.Solutions&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; %&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;filename&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;pwd&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;.ToString&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt; &quot;\&quot;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;.SolutionFile.Name&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;  write-host&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#2AA198&quot;&gt;&quot;Saving&quot;&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; +&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt; $&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;filename&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#859900&quot;&gt;  $&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;.SolutionFile.SaveAs&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#859900&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#268BD2&quot;&gt;filename&lt;/span&gt;&lt;span style=&quot;color:#657B83&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#657B83&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From: &lt;a href=&quot;https://social.technet.microsoft.com/Forums/en-US/079e2964-348c-4c1d-a227-2aff10a8deeb/export-solutions-wsp-files-to-upgrade-sp-2007-customizations-to-sp-2010?forum=sharepointadminprevious&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MSDN&lt;/a&gt;&lt;/p&gt;</content>
  </entry>
</feed>
