<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://madjava.github.io/blogs/feed.xml" rel="self" type="application/atom+xml" /><link href="https://madjava.github.io/blogs/" rel="alternate" type="text/html" /><updated>2026-06-25T12:34:48+00:00</updated><id>https://madjava.github.io/blogs/feed.xml</id><title type="html">EyeOps</title><subtitle>Cloud Technology blogs and others.</subtitle><author><name>Felix Eyetan</name></author><entry><title type="html">Team Collaboration</title><link href="https://madjava.github.io/blogs/2026/06/25/team-collaboration.html" rel="alternate" type="text/html" title="Team Collaboration" /><published>2026-06-25T00:00:00+00:00</published><updated>2026-06-25T00:00:00+00:00</updated><id>https://madjava.github.io/blogs/2026/06/25/team-collaboration</id><content type="html" xml:base="https://madjava.github.io/blogs/2026/06/25/team-collaboration.html"><![CDATA[<p>A while back, I gave a talk at our team’s Away Day on the topic of team collaboration in engineering. It was part of a broader discussion we were having as a platform operations team about how we work together, and more importantly, how we <em>should</em> work together.</p>

<p>This post is an attempt to capture and expand on those ideas, drawing on two books I’d recommend to any engineer: <strong>Accelerate</strong> by Forsgren, Humble, and Kim — and <strong>Leaders Eat Last</strong> by Simon Sinek. Both of them shaped how I think about what high-performing teams actually look like.</p>

<h2 id="why-collaboration-matters-now">Why Collaboration Matters Now</h2>

<p>There’s a quote I opened my talk with:</p>

<blockquote>
  <p>“High-performing engineering organisations aren’t defined by their tools — they’re defined by how well their teams collaborate.”</p>
</blockquote>

<p>I think most engineers would nod at that, but we often don’t act like we believe it. We invest heavily in tooling, automation, and architecture — which are all important — but collaboration tends to get treated as a soft skill, something you either have or you don’t.</p>

<p>Accelerate makes a compelling case that collaboration between development, operations, security, and platform teams is one of the <em>strongest predictors</em> of delivery performance and organisational health. Not tools. Not talent density. How well teams work together.</p>

<h2 id="what-collaboration-actually-means">What Collaboration Actually Means</h2>

<p>Here’s the thing — collaboration isn’t meetings. I’ve been in plenty of organisations that have tons of meetings and very little actual collaboration. What it really comes down to is three things: shared purpose, shared context, and shared accountability.</p>

<h3 id="shared-purpose">Shared Purpose</h3>

<p>Shared purpose means everyone understands the customer impact of their work. Platform teams see themselves as enablers, not gatekeepers. Engineers understand <em>why</em> golden paths, standards, and guardrails exist — not just that they exist.</p>

<p>Without shared purpose, collaboration collapses into transactional handoffs. You end up with teams optimising for their local metrics, not the mission.</p>

<h3 id="shared-context">Shared Context</h3>

<p>Shared context means the whole team understands the landscape well enough to make good decisions without waiting for a meeting. It’s not about more communication — it’s about <em>better</em> information.</p>

<p>A lot of cognitive load in platform engineering comes from siloed knowledge. When understanding of how systems work lives in only a few senior engineers’ heads, everyone else slows down and decisions get bottlenecked. Good collaboration closes that gap.</p>

<h3 id="shared-accountability">Shared Accountability</h3>

<p>Shared accountability means teams own outcomes together. When incidents happen, people swarm to fix them instead of assigning blame. Platform teams treat developers as customers. Developers treat the platform as a contract they help shape and improve. Security, QA, and Ops are engaged early — not at the end when it’s too late to make meaningful changes.</p>

<p>In short: collaboration is not a calendar entry. It’s a culture. It’s the operating system of high-performing engineering organisations.</p>

<h2 id="challenges-we-actually-face">Challenges We Actually Face</h2>

<p>I want to be honest about what makes collaboration hard in engineering teams, because it’s not just people being difficult. There are structural things that get in the way:</p>

<ul>
  <li>Complex, multi-cloud environments and inconsistent tooling create friction at every join point between teams.</li>
  <li>Tribal knowledge — where understanding lives in a few senior engineers — makes it hard for anyone else to contribute confidently.</li>
  <li>Cognitive load around tooling, pipelines, infrastructure-as-code, and security controls means developers are often overwhelmed before they even start their actual work.</li>
  <li>Reactive culture — where teams wait for escalations rather than co-owning outcomes — kills flow.</li>
</ul>

<p>Accelerate puts it well: high cognitive load and fragmented ownership kill flow and delivery performance. That’s not just a management problem. It’s an engineering design problem.</p>

<h2 id="what-good-collaboration-looks-like">What Good Collaboration Looks Like</h2>

<h3 id="clear-contracts-and-interfaces">Clear Contracts and Interfaces</h3>

<p>High-performing teams create clear “contracts” between the platform and its consumers — APIs, SLAs, support models, and paved paths. This reduces ambiguity and accelerates delivery. When developers know what they can rely on and where the guardrails are, they can move faster with confidence.</p>

<h3 id="platform-teams-with-a-product-mindset">Platform Teams with a Product Mindset</h3>

<p>Platform engineering teams that treat developers as customers — understanding their needs, iterating on the developer experience, and measuring adoption — see significantly higher uptake and better business results. The principle is simple: make the right thing the easy thing.</p>

<h3 id="psychological-safety-and-blameless-culture">Psychological Safety and Blameless Culture</h3>

<p>Simon Sinek’s “Circle of Safety” is essentially this: people perform their best when they feel protected, not judged. Teams with trust, transparency, and blameless communication deliver better outcomes and innovate faster. Blameless post-incident reviews are a concrete way to build this — they shift the question from “who caused this?” to “what can we learn from this?”</p>

<h3 id="the-accelerate-principles-in-practice">The Accelerate Principles in Practice</h3>

<p>A few principles from Accelerate that I think are worth calling out explicitly:</p>

<ul>
  <li><strong>Fast feedback loops</strong> — quick detection and resolution of issues prevents escalation and keeps systems stable. If feedback is slow, problems compound.</li>
  <li><strong>Small batch work</strong> — limiting work-in-progress enhances flow and simplifies deployment complexity. Big batches hide problems.</li>
  <li><strong>Reducing handoff friction</strong> — minimising handoffs shortens cycle times and empowers teams to deliver independently. Every handoff is a delay and a potential loss of context.</li>
  <li><strong>Learning culture</strong> — encouraging blameless post-incident reviews fosters experimentation and organisational resilience.</li>
</ul>

<h2 id="what-leadership-enables">What Leadership Enables</h2>

<p>This isn’t just about individual engineers doing better. Leadership behaviours matter enormously here.</p>

<p>When leaders create a Circle of Safety — protecting their teams rather than exposing them to unnecessary risk or blame — teams thrive. When psychological safety is present, people surface risks early instead of hiding them until they become incidents. When engineers are given real autonomy and their experimentation is supported, you get innovation.</p>

<p>Celebrating learning — not just success — reinforces the right behaviours. An engineer who tried something, failed safely, and learned something valuable is worth more than an engineer who never risks anything. Recognition should reflect that.</p>

<h2 id="outcomes-worth-working-towards">Outcomes Worth Working Towards</h2>

<p>When collaboration is genuinely working, you tend to see:</p>

<ul>
  <li><strong>Faster delivery and safer changes</strong> — streamlined workflows and reduced coordination overhead mean teams can ship faster without cutting corners on safety.</li>
  <li><strong>Reduced cognitive load</strong> — golden paths, self-service tools, and consistent documentation mean developers spend less time fighting the platform and more time solving real problems.</li>
  <li><strong>Better reliability and faster recovery</strong> — shared ownership and rapid feedback loops increase platform reliability and reduce mean time to recovery.</li>
  <li><strong>Better morale and retention</strong> — strong collaboration builds trust. And trust is what makes people want to stay.</li>
</ul>

<h2 id="where-to-start">Where to Start</h2>

<p>If I had to leave you with one practical takeaway: pick one new collaboration practice and measure its impact.</p>

<p>That could be introducing blameless post-incident reviews. It could be setting up a clearer SLA between your platform team and your developers. It could be cutting a paved path for a workflow that currently requires tribal knowledge. It could be as simple as changing how your team runs a retrospective.</p>

<p>Collaboration transforms capability into impact. It’s how we deliver secure, reliable, user-centred services at scale — not just individually, but as a team.</p>]]></content><author><name>Felix Eyetan</name></author><category term="Platform Eng" /><category term="Leadership" /><summary type="html"><![CDATA[A while back, I gave a talk at our team’s Away Day on the topic of team collaboration in engineering. It was part of a broader discussion we were having as a platform operations team about how we work together, and more importantly, how we should work together.]]></summary></entry><entry><title type="html">Managing TLS Policies in Azure Front Door with Terraform and AzAPI</title><link href="https://madjava.github.io/blogs/2025/12/13/azure-frontdoor-custom-cipher.html" rel="alternate" type="text/html" title="Managing TLS Policies in Azure Front Door with Terraform and AzAPI" /><published>2025-12-13T00:00:00+00:00</published><updated>2025-12-13T00:00:00+00:00</updated><id>https://madjava.github.io/blogs/2025/12/13/azure-frontdoor-custom-cipher</id><content type="html" xml:base="https://madjava.github.io/blogs/2025/12/13/azure-frontdoor-custom-cipher.html"><![CDATA[<p>Azure Front Door supports end-to-end TLS encryption. When you add a custom domain to Azure Front Door, HTTPS is mandatory, and you must define a TLS policy that controls the TLS protocol version and cipher suites during the handshake.</p>

<p>This is outlined in the official Azure Front Door TLS policy documentation, which explains how Azure Front Door (AFD) manages TLS and cipher suites.</p>

<h3 id="the-challenge">The Challenge</h3>

<p>The documentation clearly states that the predefined TLS policy is <code class="language-plaintext highlighter-rouge">TLSv1.2_2023</code> under the <a href="https://learn.microsoft.com/en-us/azure/frontdoor/standard-premium/tls-policy#predefined-tls-policy">Predefined TLS policy</a> section.</p>

<p>As of <strong>March 1, 2025</strong>, Azure Front Door disallows <code class="language-plaintext highlighter-rouge">TLS 1.0</code> and <code class="language-plaintext highlighter-rouge">TLS 1.1</code> as minimum versions. To comply, our organization updated the minimum TLS version to <code class="language-plaintext highlighter-rouge">TLS 1.2</code>.</p>

<h4 id="why-tls-12-and-not-tls-13">Why TLS 1.2 and not TLS 1.3?</h4>

<p>According to the documentation:</p>

<blockquote>
  <p>For a minimum TLS version of 1.2, the negotiation will attempt to establish TLS 1.3 first, then fall back to TLS 1.2. The client must support at least one of the supported ciphers to establish an HTTPS connection with Azure Front Door. Azure Front Door chooses a cipher in the listed order from the client-supported ciphers.</p>
</blockquote>

<p>In other words, AFD will always try <code class="language-plaintext highlighter-rouge">TLS 1.3</code> first. If the client supports any advertised cipher, the connection succeeds; otherwise, it falls back to the minimum version (<code class="language-plaintext highlighter-rouge">TLS 1.2</code> in our case).</p>

<h4 id="after-recent-ithcs">After Recent ITHCs</h4>

<p>Following recent ITHC assessments, our SecOps team raised concerns about weak ciphers being advertised on endpoints—particularly those handling PCI DSS data. They requested that Platform Engineering address this issue.</p>

<h3 id="afd-limitations">AFD Limitations</h3>

<p>Reviewing our Azure Front Door configuration revealed that we could switch from <code class="language-plaintext highlighter-rouge">TLSv1.2_2022</code> to <code class="language-plaintext highlighter-rouge">TLSv1.2_2023</code> (which uses stronger ciphers). However, making this change manually in the Azure Portal was ineffective because our resources were deployed via Terraform. Any manual updates were reverted during subsequent pipeline runs.</p>

<p>As of <strong>Nov/Dec 2025</strong>, the Terraform provider <a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/cdn_frontdoor_custom_domain"><code class="language-plaintext highlighter-rouge">azurerm_cdn_frontdoor_custom_domain</code></a> (v4.56.0) does <strong>not</strong> support configuring the TLS policy cipher suite. Azure defaults to <code class="language-plaintext highlighter-rouge">TLSv1.2_2022</code>, which was surprising given the documentation suggested otherwise (see <a href="#why-tls-12-and-not-tls-13">Why TLS 1.2 and not TLS 1.3?</a>).</p>

<h3 id="the-solution">The Solution</h3>

<p>To meet security requirements and stop advertising weaker ciphers, i implemented a workaround using the <strong>AzAPI provider</strong> alongside Terraform.</p>

<h4 id="code-changes">Code Changes</h4>

<p>Here’s a simplified extract of the changes to the custom domain resource:</p>

<div class="language-terraform highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">resource</span> <span class="s2">"azurerm_cdn_frontdoor_custom_domain"</span> <span class="s2">"this"</span> <span class="p">{</span>
  <span class="p">...</span>
  <span class="nx">tls</span> <span class="p">{</span>
    <span class="nx">certificate_type</span>        <span class="p">=</span> <span class="s2">"CustomerCertificate"</span>
    <span class="nx">minimum_tls_version</span>     <span class="p">=</span> <span class="s2">"TLS12"</span>
    <span class="nx">cdn_frontdoor_secret_id</span> <span class="p">=</span> <span class="nx">azurerm_cdn_frontdoor_secret</span><span class="p">.</span><span class="nx">certificate</span><span class="p">[</span><span class="nx">each</span><span class="p">.</span><span class="nx">key</span><span class="p">].</span><span class="nx">id</span> <span class="err">:</span> <span class="kc">null</span>
  <span class="p">}</span>

  <span class="nx">lifecycle</span> <span class="p">{</span>
    <span class="c1"># Prevent Terraform from overwriting TLS policy changes applied via AzAPI</span>
    <span class="nx">ignore_changes</span> <span class="p">=</span> <span class="p">[</span> <span class="nx">tls</span> <span class="p">]</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">ignore_changes</code> directive ensures Terraform does not revert TLS policy changes applied by AzAPI. Without this, pipeline runs would reset the configuration, similar to what happens when changes are made manually in the portal.</p>

<h4 id="why-azapi">Why AzAPI?</h4>

<p>The <a href="https://registry.terraform.io/providers/Azure/azapi/latest/docs">documentation</a> states:</p>

<blockquote>
  <p>The AzAPI provider is a thin layer on top of Azure ARM REST APIs. It complements the AzureRM provider by enabling management of Azure resources not yet supported in AzureRM—such as preview features or advanced configurations.</p>
</blockquote>

<h4 id="azapi-resource-for-tls-policy">AzAPI Resource for TLS Policy</h4>

<p>In addition to the changes mage to the <code class="language-plaintext highlighter-rouge">azurerm_cdn_frontdoor_custom_domain</code> above, the below azapi code was added.</p>

<div class="language-terraform highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">resource</span> <span class="s2">"azapi_update_resource"</span> <span class="s2">"this"</span> <span class="p">{</span>
  <span class="p">...</span>
  <span class="nx">type</span>        <span class="p">=</span> <span class="s2">"Microsoft.Cdn/profiles/customDomains@2025-04-15"</span>
  <span class="nx">resource_id</span> <span class="p">=</span> <span class="nx">azurerm_cdn_frontdoor_custom_domain</span><span class="p">.</span><span class="nx">this</span><span class="p">.</span><span class="nx">id</span>

  <span class="nx">body</span> <span class="p">=</span> <span class="nx">jsonencode</span><span class="p">({</span>
    <span class="nx">properties</span> <span class="p">=</span> <span class="p">{</span>
      <span class="nx">tlsSettings</span> <span class="p">=</span> <span class="p">{</span>
        <span class="nx">minimumTlsVersion</span>  <span class="p">=</span> <span class="kd">var</span><span class="p">.</span><span class="nx">minimum_tls_version</span>
        <span class="nx">cipherSuiteSetType</span> <span class="p">=</span> <span class="kd">var</span><span class="p">.</span><span class="nx">cipher_suite_policy</span>
        <span class="c1"># certificateType   = "ManagedCertificate" (if needed as well)</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">})</span>

  <span class="nx">depends_on</span> <span class="p">=</span> <span class="p">[</span>
    <span class="nx">azurerm_cdn_frontdoor_custom_domain</span><span class="p">.</span><span class="nx">this</span>
  <span class="p">]</span>
<span class="p">}</span>
</code></pre></div></div>

<p>By specifying the <code class="language-plaintext highlighter-rouge">"Microsoft.Cdn/profiles/customDomains@2025-04-15"</code> API version, we gain access to the full <code class="language-plaintext highlighter-rouge">tlsSettings</code> properties, including <code class="language-plaintext highlighter-rouge">cipherSuiteSetType</code>. This allows us to configure cipher suites while keeping Terraform pipelines stable i.e. terraform not trying to <code class="language-plaintext highlighter-rouge">destroy</code> and <code class="language-plaintext highlighter-rouge">recreate</code> existing resources. This allow us to keep existing code as is but gave the capability to now change the cipher suite used.</p>

<h4 id="variable-definitions-with-validation">Variable Definitions with Validation</h4>

<p>To make this configurable and reduce errors, i now added validation to the <code class="language-plaintext highlighter-rouge">cipher_suite_policy</code> variable:</p>

<div class="language-terraform highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">variable</span> <span class="s2">"minimum_tls_version"</span> <span class="p">{</span>
  <span class="nx">type</span>        <span class="p">=</span> <span class="nx">string</span>
  <span class="nx">description</span> <span class="p">=</span> <span class="s2">"The default TLS policy to apply to Front Door custom domain."</span>
  <span class="nx">default</span>     <span class="p">=</span> <span class="s2">"TLS12"</span> <span class="c1"># Could be TLS13 depending on your use case</span>
<span class="p">}</span>

<span class="k">variable</span> <span class="s2">"cipher_suite_policy"</span> <span class="p">{</span>
  <span class="nx">description</span> <span class="p">=</span> <span class="o">&lt;&lt;-</span><span class="no">EOT</span><span class="sh">
  TLS policy preset for Azure Front Door custom domains.
  Options:
    - null: Use Azure's default policy
    - "TLS12_2022": More compatible (includes DHE cipher suites)
    - "TLS12_2023": Higher security (may exclude older cipher suites)
</span><span class="no">  EOT

</span>  <span class="nx">type</span>    <span class="p">=</span> <span class="nx">string</span>
  <span class="nx">default</span> <span class="p">=</span> <span class="kc">null</span> <span class="c1"># Let Azure decide the default</span>

  <span class="nx">validation</span> <span class="p">{</span>
    <span class="nx">condition</span>     <span class="p">=</span> <span class="kd">var</span><span class="p">.</span><span class="nx">cipher_suite_policy</span> <span class="p">==</span> <span class="kc">null</span> <span class="err">?</span> <span class="kc">true</span> <span class="err">:</span> <span class="nx">contains</span><span class="p">([</span><span class="s2">"TLS12_2022"</span><span class="p">,</span> <span class="s2">"TLS12_2023"</span><span class="p">],</span> <span class="kd">var</span><span class="p">.</span><span class="nx">cipher_suite_policy</span><span class="p">)</span>
    <span class="nx">error_message</span> <span class="p">=</span> <span class="s2">"Must be null, 'TLS12_2022', or 'TLS12_2023'"</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>This ensures only valid cipher suite policies are used, reducing misconfigurations.</p>

<h3 id="validation">Validation</h3>

<p>A great tool for validation is <a href="https://www.ssllabs.com/ssltest/">SSL Labs Server Test</a>. Enter your domain name, run a scan, and review the results. It provides detailed TLS information, including advertised cipher suites.</p>

<p><strong>Key Takeaways:</strong></p>

<ul>
  <li>Azure Front Door defaults may not align with your security requirements.</li>
  <li>Terraform currently lacks native support for cipher suite configuration.</li>
  <li>AzAPI provides a reliable workaround until the AzureRM provider adds this capability.</li>
  <li>Solution keeps existing resource, but provides more flexibility.</li>
  <li>More code is introduced to existing code base.</li>
  <li>Always validate changes using SSL testing tools.</li>
  <li>Setting minimum TLS to <code class="language-plaintext highlighter-rouge">TLS1.3</code> maybe all you need and above code changes not needed.</li>
  <li>Minimum TLS as <code class="language-plaintext highlighter-rouge">TLS1.3</code> may have implications for some clients, if so then above suggestion may work for you.</li>
  <li>These setting don’t change much, once set they usually are that way for a while.</li>
</ul>

<h3 id="reference-docs">Reference Docs</h3>

<ul>
  <li><a href="https://learn.microsoft.com/en-us/azure/frontdoor/standard-premium/tls-policy-configure">Configure TLS policy on a Front Door custom domain</a></li>
  <li><a href="https://registry.terraform.io/providers/Azure/azapi/latest/docs/resources/update_resource">azapi_update_resource (Resource)</a></li>
  <li><a href="https://learn.microsoft.com/en-us/answers/questions/1296563/how-to-limit-azure-front-door-cipher-suites-manual?page=1#answers">How to limit Azure Front Door Cipher Suites Manually?</a></li>
  <li><a href="https://github.com/hashicorp/terraform-provider-azurerm/issues/29215">azurerm_cdn_frontdoor - Support for TLS Policy #29215</a></li>
  <li><a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/cdn_frontdoor_custom_domain">azurerm_cdn_frontdoor_custom_domain</a></li>
</ul>]]></content><author><name>Felix Eyetan</name></author><category term="Azure" /><category term="IaC" /><summary type="html"><![CDATA[Azure Front Door supports end-to-end TLS encryption. When you add a custom domain to Azure Front Door, HTTPS is mandatory, and you must define a TLS policy that controls the TLS protocol version and cipher suites during the handshake.]]></summary></entry><entry><title type="html">JumpBox vs JumpServer vs Azure Bastion – What’s the Difference?</title><link href="https://madjava.github.io/blogs/2025/11/22/azure-bastion.html" rel="alternate" type="text/html" title="JumpBox vs JumpServer vs Azure Bastion – What’s the Difference?" /><published>2025-11-22T00:00:00+00:00</published><updated>2025-11-22T00:00:00+00:00</updated><id>https://madjava.github.io/blogs/2025/11/22/azure-bastion</id><content type="html" xml:base="https://madjava.github.io/blogs/2025/11/22/azure-bastion.html"><![CDATA[<p>When you need secure remote access to virtual machines (VMs) in Azure, or any corporate network in general, you’ll quickly come across terms like <strong>JumpBox</strong>, <strong>JumpServer</strong>, and <strong>Azure Bastion</strong>. They all provide secure access to private networks, but they work differently and suit different environments.</p>

<p>This guide breaks each option down in a clear way to help you decide which one fits your use case.</p>

<h2 id="what-is-a-jumpbox">What Is a JumpBox?</h2>

<p>A <strong>JumpBox</strong> (also called a jump host or bastion host) is a VM deployed in your virtual network that you first log into before accessing other internal systems. Instead of exposing multiple VMs to the internet, you lock down just this one box and use it as your gateway.</p>

<h3 id="why-teams-use-jumpboxes">Why Teams Use JumpBoxes</h3>

<ul>
  <li><strong>Easy to set up</strong> – Deploy a VM, configure access, and you’re good to go.</li>
  <li><strong>Low cost</strong> – No extra licensing or complicated installations.</li>
  <li><strong>Customisable</strong> – Install scripts, Azure CLI, SSH tools, management consoles—whatever you need.</li>
</ul>

<h3 id="drawbacks-of-jumpboxes">Drawbacks of JumpBoxes</h3>

<ul>
  <li><strong>Not ideal at scale</strong> – Gets messy with many users or many VMs.</li>
  <li><strong>Maintenance overhead</strong> – You handle patching, NSGs, MFA, certificates and hardening.</li>
  <li><strong>Single point of failure</strong> – If the JumpBox is down, so is access.</li>
  <li><strong>Costs can increase over time</strong> – Multiple teams might need multiple JumpBoxes.</li>
</ul>

<p>JumpBoxes are perfect for small environments, but long-term you start feeling the pain.</p>

<h2 id="what-is-a-jumpserver">What Is a JumpServer?</h2>

<p>A <strong>JumpServer</strong> is the enterprise upgrade of a JumpBox. Instead of a single VM, it’s a full access management platform with centralised controls, identity integrations, and security auditing.</p>

<p>Think of it as a <strong>Privileged Access Management (PAM)</strong> platform built for remote access.</p>

<h3 id="why-teams-use-jumpservers">Why Teams Use JumpServers</h3>

<ul>
  <li>One place to manage all access</li>
  <li>Enterprise-grade security, including:
    <ul>
      <li>Session recording</li>
      <li>Detailed auditing</li>
      <li>MFA integration</li>
      <li>Privileged user policies</li>
    </ul>
  </li>
  <li>Designed for scale</li>
  <li>RBAC support</li>
  <li>Directory integration – Works with AD or Azure AD to automate onboarding/offboarding.</li>
  <li>Protocol flexibility – SSH, RDP, VNC, etc.</li>
</ul>

<h3 id="popular-jumpserver-solutions">Popular JumpServer Solutions</h3>

<p>Open source:</p>

<ul>
  <li><a href="https://guacamole.apache.org/">Apache Guacamole</a></li>
  <li><a href="https://goteleport.com/ssh-jump-server/">Teleport</a></li>
</ul>

<p>Commercial:</p>

<ul>
  <li><a href="https://www.beyondtrust.com/">BeyondTrust</a></li>
  <li><a href="https://www.cyberark.com/">CyberArk</a></li>
  <li><a href="https://azure.microsoft.com/en-us/products/azure-bastion#Overview-2">Azure Bastion</a> <em>(discussed below)</em></li>
</ul>

<h3 id="downsides-of-jumpservers">Downsides of JumpServers</h3>

<ul>
  <li>More complex to deploy</li>
  <li>Higher operational cost</li>
  <li>Users may need training</li>
  <li>More infrastructure required</li>
  <li>Some products rely on third-party components</li>
</ul>

<p>If you need strong auditing, compliance, and centralised security, JumpServers are the way to go.</p>

<h2 id="what-is-azure-bastion">What Is Azure Bastion?</h2>

<p><strong>Azure Bastion</strong> is a fully managed, cloud-native alternative to running your own jump host. Instead of maintaining a JumpBox or JumpServer, Azure handles the infrastructure for you.</p>

<p>You connect to VMs directly through the Azure portal—<strong>even when the VMs have no public IP addresses</strong>.</p>

<h3 id="why-azure-bastion-stands-out">Why Azure Bastion Stands Out</h3>

<ul>
  <li>No public exposure of VMs</li>
  <li>Nothing to patch or maintain</li>
  <li>Browser-based access from the Azure portal</li>
  <li>RBAC, Conditional Access, and Azure security integration</li>
  <li>Scales automatically</li>
  <li>Premium features available, such as:
    <ul>
      <li>SSH/RDP tunneling</li>
      <li>File transfer</li>
      <li>Private Link</li>
      <li>Local client connectivity</li>
    </ul>
  </li>
</ul>

<h3 id="limitations-of-azure-bastion">Limitations of Azure Bastion</h3>

<ul>
  <li><strong>Not free</strong> – Pricing is per hour plus data throughput.</li>
  <li><strong>Azure-only</strong> – No native multi-cloud support.</li>
  <li><strong>Doesn’t replace enterprise PAM</strong> – No session recording (none premium SKUs) or password vaulting.</li>
  <li><strong>Microsoft controls maintenance and updates</strong> – Good most of the time, but limited control if you need deep customisation.</li>
</ul>

<p>For most Azure-centric environments, Bastion offers a clean and secure experience without the overhead of managing infrastructure.</p>

<h2 id="quick-comparison-table">Quick Comparison Table</h2>

<table>
  <thead>
    <tr>
      <th style="text-align: left">Feature</th>
      <th style="text-align: center">JumpBox</th>
      <th style="text-align: center">JumpServer</th>
      <th style="text-align: center">Azure Bastion</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td style="text-align: left"><strong>Type</strong></td>
      <td style="text-align: center">Single VM gateway</td>
      <td style="text-align: center">Access management platform</td>
      <td style="text-align: center">Fully managed service</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>Best For</strong></td>
      <td style="text-align: center">Small environments</td>
      <td style="text-align: center">Large enterprise teams</td>
      <td style="text-align: center">Cloud-native secure access</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>Setup Complexity</strong></td>
      <td style="text-align: center">Low</td>
      <td style="text-align: center">Medium–High</td>
      <td style="text-align: center">Very low</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>Maintenance</strong></td>
      <td style="text-align: center">High</td>
      <td style="text-align: center">Medium–High</td>
      <td style="text-align: center">None</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>Session Recording</strong></td>
      <td style="text-align: center">No</td>
      <td style="text-align: center">Yes</td>
      <td style="text-align: center">No <em>(see <a href="https://learn.microsoft.com/en-us/azure/bastion/session-recording">Premium SKU</a>)</em></td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>Public IP Needed</strong></td>
      <td style="text-align: center">Usually yes</td>
      <td style="text-align: center">Optional</td>
      <td style="text-align: center">Optional</td>
    </tr>
    <tr>
      <td style="text-align: left"><strong>Cost</strong></td>
      <td style="text-align: center">Low (initial)</td>
      <td style="text-align: center">Medium–High</td>
      <td style="text-align: center">Medium</td>
    </tr>
  </tbody>
</table>

<h2 id="next-steps">Next Steps</h2>

<p>If you want to go deeper:</p>

<ul>
  <li>
    <p>Learn more from Microsoft’s docs: <a href="https://learn.microsoft.com/en-us/azure/bastion/bastion-overview">Bastion Overview</a></p>
  </li>
  <li>
    <p>I also have a step-by-step walkthrough on deploying Azure Bastion using Terraform here:<br />
<a href="https://xxx">Azure Bastion Capabilities</a>.</p>
  </li>
</ul>

<h2 id="final-thoughts">Final Thoughts</h2>

<p>JumpBoxes, JumpServers, and Azure Bastion all help you securely connect to private systems, but they solve the problem differently:</p>

<ul>
  <li><strong>JumpBox:</strong> Fast and cheap, but high maintenance.</li>
  <li><strong>JumpServer:</strong> Enterprise-grade control, auditing, and PAM features.</li>
  <li><strong>Azure Bastion:</strong> Cloud-native, secure, and zero maintenance.</li>
</ul>

<p>For most modern Azure deployments, <a href="https://learn.microsoft.com/en-us/azure/bastion/">Azure Bastion</a> provides the best balance of simplicity, security, and scalability, especially if you want strong protection without managing additional infrastructure.</p>]]></content><author><name>Felix Eyetan</name></author><category term="Azure" /><category term="Security" /><summary type="html"><![CDATA[When you need secure remote access to virtual machines (VMs) in Azure, or any corporate network in general, you’ll quickly come across terms like JumpBox, JumpServer, and Azure Bastion. They all provide secure access to private networks, but they work differently and suit different environments.]]></summary></entry><entry><title type="html">Azure Frontdoor security capabilities</title><link href="https://madjava.github.io/blogs/2025/10/23/azure-frontdoor-security-capabilities.html" rel="alternate" type="text/html" title="Azure Frontdoor security capabilities" /><published>2025-10-23T00:00:00+00:00</published><updated>2025-10-23T00:00:00+00:00</updated><id>https://madjava.github.io/blogs/2025/10/23/azure-frontdoor-security-capabilities</id><content type="html" xml:base="https://madjava.github.io/blogs/2025/10/23/azure-frontdoor-security-capabilities.html"><![CDATA[<p>While Azure Front Door’s WAF, DDoS protection, and SSL termination provide <strong>excellent foundational security</strong>, they may not be sufficient <strong>alone</strong> for many enterprise scenarios.</p>

<h2 id="what-front-door-security-covers-well">What Front Door Security Covers Well</h2>

<h3 id="front-doors-strengths">Front Door’s Strengths</h3>

<p>WAF Protection:</p>

<ul>
  <li>OWASP Top 10 coverage (SQLi, XSS, etc.)</li>
  <li>Managed rulesets (Microsoft &amp; Bot Manager)</li>
  <li>Custom rules for specific patterns</li>
  <li>Geographic filtering</li>
  <li>Rate limiting</li>
</ul>

<p>DDoS Protection:</p>

<ul>
  <li>Always-on traffic monitoring</li>
  <li>Auto-mitigation at edge locations</li>
  <li>Scale to absorb large attacks</li>
  <li>No additional cost with Front Door Premium</li>
</ul>

<p>SSL/TLS:</p>

<ul>
  <li>Certificate management</li>
  <li>TLS termination at edge</li>
  <li>Perfect forward secrecy</li>
  <li>HTTP/2 support</li>
</ul>

<h2 id="critical-security-gaps-in-front-door-only-approach">Critical Security Gaps in Front Door-Only Approach</h2>

<h3 id="major-limitations">Major Limitations</h3>

<h4 id="1-no-network-level-inspection">1. No Network-Level Inspection</h4>

<p><strong>Front Door operates at Layer 7 only</strong></p>

<p><strong>Missing:</strong></p>

<ul>
  <li>IP reputation filtering beyond geo-blocking</li>
  <li>Protocol anomaly detection</li>
  <li>TCP/UDP flood protection (only HTTP/HTTPS)</li>
  <li>Stateful packet inspection</li>
</ul>

<h4 id="2-limited-visibility--control">2. Limited Visibility &amp; Control</h4>

<p><strong>What you CAN’T see/do with Front Door alone:</strong></p>

<ul>
  <li>Full packet capture for forensics</li>
  <li>Deep packet inspection for encrypted traffic</li>
  <li>Intrusion Detection/Prevention System (IDS/IPS)</li>
  <li>Advanced threat intelligence feeds</li>
</ul>

<h4 id="3-backend-exposure-risks">3. Backend Exposure Risks</h4>

<p><strong>Potential attack vectors that bypass Front Door:</strong></p>

<ul>
  <li>Direct IP attacks (if backend IPs are exposed)</li>
  <li>Lateral movement if a VM is compromised</li>
  <li>Outbound callbacks to Command &amp; Control servers</li>
  <li>Data exfiltration attempts</li>
</ul>

<h4 id="4-compliance--governance-gaps">4. Compliance &amp; Governance Gaps</h4>

<p><strong>Regulatory requirements often need:</strong></p>

<ul>
  <li>Unified security policy enforcement</li>
  <li>Centralized logging across all layers</li>
  <li>Network segmentation controls</li>
  <li>Egress filtering and inspection</li>
</ul>

<h2 id="when-front-door-alone-might-be-sufficient">When Front Door Alone Might Be Sufficient</h2>

<h3 id="appropriate-use-cases">Appropriate Use Cases</h3>

<p><strong>Simple Web Applications:</strong></p>

<ul>
  <li>Brochure websites</li>
  <li>Marketing sites</li>
  <li>Low-sensitivity content</li>
  <li>No regulatory requirements</li>
</ul>

<p><strong>Development Environments:</strong></p>

<ul>
  <li>Staging/Test environments</li>
  <li>Proof-of-concept apps</li>
  <li>Non-production workloads</li>
</ul>

<p><strong>Complementary to Other Security:</strong></p>

<ul>
  <li>Already have robust backend security</li>
  <li>Using API Management with its own WAF</li>
  <li>Containerized apps with service mesh security</li>
</ul>

<h2 id="recommended-layered-security-approach">Recommended Layered Security Approach</h2>

<h3 id="️-defense-in-depth-architecture">🛡️ <strong>Defense in Depth Architecture</strong></h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>┌─────────────────────────────────────────────────────────────┐
│                    INTERNET TRAFFIC                         │
└─────────────────────────────┬───────────────────────────────┘
                              │
┌─────────────────────────────▼───────────────────────────────┐
                 Azure Front Door Premium                     
    ✅ WAF | ✅ DDoS | ✅ SSL | ✅ Bot Protection            
└─────────────────────────────┬───────────────────────────────┘
                              │
┌─────────────────────────────▼───────────────────────────────┐
                 Azure Firewall / Other NVA's                
    ✅ Network Inspection | ✅ IDS/IPS | ✅ Threat Intel     
└─────────────────────────────┬───────────────────────────────┘
                              │
┌─────────────────────────────▼───────────────────────────────┐
        Private Endpoints / Internal LoadBalancers                      
    ✅ Network Isolation | ✅ No Public IPs                  
└─────────────────────────────┬───────────────────────────────┘
                              │
┌─────────────────────────────▼───────────────────────────────┐
                 Backend Application                          
    ✅ App Security | ✅ Authentication | ✅ Authorization    
└─────────────────────────────────────────────────────────────┘
</code></pre></div></div>

<h2 id="specific-scenarios-requiring-additional-protection">Specific Scenarios Requiring Additional Protection</h2>

<h3 id="high-risk-environments">High-Risk Environments</h3>

<p><strong>Financial Services:</strong></p>

<ul>
  <li>Need: Transaction monitoring, fraud detection</li>
  <li>Gap: Front Door doesn’t provide behavioral analytics</li>
</ul>

<p><strong>Healthcare (HIPAA):</strong></p>

<ul>
  <li>Need: Comprehensive audit trails, data loss prevention</li>
  <li>Gap: Limited egress control and data inspection</li>
</ul>

<p><strong>Government (FedRAMP):</strong></p>

<ul>
  <li>Need: Network segmentation, intrusion detection</li>
  <li>Gap: No network-level security controls</li>
</ul>

<p><strong>E-commerce:</strong></p>

<ul>
  <li>Need: Real-time threat intelligence, bot management</li>
  <li>Gap: Basic bot protection may not stop sophisticated attacks</li>
</ul>

<h2 id="cost-vs-security-trade-off">Cost vs. Security Trade-off</h2>

<h3 id="security-investment-matrix">Security Investment Matrix</h3>

<p><strong>Basic Security (Lower Cost)</strong>
Azure Front Door Standard: ~$15-50/month</p>

<ul>
  <li>Suitable for: Dev, test, low-risk apps</li>
</ul>

<p><strong>Enhanced Security (Medium Investment)</strong>
Azure Front Door Premium: ~$200-500/month
Azure Firewall Basic: ~$200-400/month</p>

<ul>
  <li>Suitable for: Most production workloads</li>
</ul>

<p><strong>Enterprise Security (Higher Investment)</strong>
Azure Front Door Premium: ~$200-500/month
Azure Firewall Premium: ~$1,000-2,000/month
Third-party WAF/NVA: ~$500-1,500/month</p>

<ul>
  <li>Suitable for: High-security, regulated environments</li>
</ul>

<p><em>Figures will vary, use the <a href="https://azure.microsoft.com/en-gb/pricing/calculator/">Azure pricing calculator</a> to get current values.</em></p>

<h2 id="final-recommendation">Final Recommendation</h2>

<p>For most production applications, I recommend combining Front Door with Azure Firewall</p>

<p><strong>Minimum Production Setup:</strong></p>

<ul>
  <li>Azure Front Door Premium (for advanced WAF &amp; bot protection)</li>
  <li>Azure Firewall Standard (for network inspection)</li>
  <li>Private Endpoints (to eliminate public backend exposure)</li>
  <li>NSGs &amp; Route Tables (for micro-segmentation)</li>
</ul>

<p><strong>Enterprise Security Setup:</strong></p>

<ul>
  <li>Azure Front Door Premium</li>
  <li>Azure Firewall Premium (for IDS/IPS/TLS inspection)</li>
  <li>Microsoft Defender for Cloud (threat protection)</li>
  <li>Azure Sentinel (SIEM/SOAR)</li>
  <li>Regular penetration testing</li>
</ul>

<p><strong>Bottom Line:</strong></p>

<p>Front Door provides excellent application-layer security, but defense in depth requires additional network-level controls, especially for sensitive data, compliance requirements, or high-value applications. Taking a multi-layered approach is advisable especially at the enterprise level.</p>]]></content><author><name>Felix Eyetan</name></author><category term="Azure" /><category term="Security" /><summary type="html"><![CDATA[While Azure Front Door’s WAF, DDoS protection, and SSL termination provide excellent foundational security, they may not be sufficient alone for many enterprise scenarios.]]></summary></entry><entry><title type="html">Simple ways to use Git</title><link href="https://madjava.github.io/blogs/2025/05/03/git-in-simple-ways.html" rel="alternate" type="text/html" title="Simple ways to use Git" /><published>2025-05-03T00:00:00+00:00</published><updated>2025-05-03T00:00:00+00:00</updated><id>https://madjava.github.io/blogs/2025/05/03/git-in-simple-ways</id><content type="html" xml:base="https://madjava.github.io/blogs/2025/05/03/git-in-simple-ways.html"><![CDATA[<h3 id="assumptions">Assumptions</h3>

<ul>
  <li>You have Git <a href="https://git-scm.com/book/en/v2/Getting-Started-Installing-Git">installed</a> on your local machine</li>
  <li>You have either a <a href="https://github.com/">GitHub</a> or <a href="https://bitbucket.org/">BitBucket</a> account.</li>
  <li>You have a terminal tool or an <a href="https://www.geeksforgeeks.org/what-is-ide/">IDE</a> that provided one
    <ul>
      <li><a href="https://bitbucket.org/">iTerm</a> is nice if using a Mac</li>
    </ul>
  </li>
</ul>

<h3 id="what-is-git">What is Git</h3>

<p><a href="https://git-scm.com/">Git</a> is a fast and modern implementation of version control. It provides a history of content
changes and facilitates collaborative changes to files.</p>

<h3 id="why-do-i-need-git">Why do I need Git</h3>

<ul>
  <li>Fast and easy to setup and learn</li>
  <li>Locally enable and distributed</li>
  <li>Good history tracking features</li>
  <li>Good for collaboration</li>
  <li>Lots of tools, features and documentation</li>
  <li>A large community of users</li>
</ul>

<h3 id="git-is-not-github">Git is not GitHub</h3>

<p>👉🏽 <strong>Git</strong> is a version control system that let’s you manage and keep track of your source code history.</p>

<p>👉🏽 <strong>GitHub</strong> is a cloud-based hosting service that let’s you manage Git repositories. It has additional capabilities around tooling, pipelines, security and a bunch of others useful features.</p>

<p>If you have open-source projects that use Git, then GitHub is designed to help you better manage them.</p>

<h3 id="the-basics---setting-up">The Basics - Setting up</h3>

<h4 id="creating-a-git-repository">Creating a Git repository</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git init 
</code></pre></div></div>

<p>The name <code class="language-plaintext highlighter-rouge">main</code> will be used by default.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git init -b master
</code></pre></div></div>

<p>If using another branch name, you can replace <code class="language-plaintext highlighter-rouge">master</code> with a name of your preference, but <code class="language-plaintext highlighter-rouge">main</code> (modern) or <code class="language-plaintext highlighter-rouge">master</code> (legacy) will suffice.</p>

<p>For your day-to-day projects or if working in collaboration with others, you will want to store content in a more central location such as GitHub or BitBucket best to create a new repository (repo) and the clone to your local machine.</p>

<p>To do so, from your GitHub account for example, create a new repo, then clone that i.e. make a copy of it on your local machine using the commands below in your terminal of choice.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone &lt;REMOTE_URL&gt;
</code></pre></div></div>

<p>You will notice a new folder in the location you executed the command from.</p>

<h4 id="synching-your-git-repo">Synching your git repo</h4>

<p>If you already have a local git repo by <a href="#creating-a-git-repository">initialing</a> git locally, you can point it (connect it) to an existing remote repo.</p>

<p>A remote repo is a repo that exists in another location that uses Git e.g. <a href="https://github.com/">GitHub</a> or <a href="https://bitbucket.org/product/">BitBucket</a>.</p>

<p>The below command can help you achieve this.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git remote add origin &lt;REMOTE_URL&gt;
git checkout &lt;REMOTE_URL&gt;
</code></pre></div></div>

<p>Your local repo will now point to your remove repo, meaning when you push changes the remote repo will get those changes.</p>

<p><em><strong>Note:</strong> Watch out for discrepancies aka <code class="language-plaintext highlighter-rouge">merge</code> conflicts if files already exists in either repositories. You may have to take further <a href="#merging-rebasing-and-reverting">actions</a> to resolve them</em></p>

<h3 id="branching-and-switching">Branching and Switching</h3>

<p>A branch represents an independent line of development, like a silo. When working in collaboration with others, you create a branch, a copy of the project, where you can experiment with your ideas make change and not affect the main body of work.</p>

<p>You may also invite collaborators to review your work on your branch where contributions will be added to it and reviews received.</p>

<h4 id="creating-a-branch">Creating a branch</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git branch &lt;branch-name&gt; 
</code></pre></div></div>

<p><em>Note: You don’t really have a branch until you add or commit a file to the new branch</em></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git checkout -b &lt;new-branch&gt;
git checkout -b &lt;new-branch&gt; &lt;existing-branch&gt;
</code></pre></div></div>

<h4 id="switching-branches">Switching branches</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git fetch –all
</code></pre></div></div>

<p><em>Optional, but sometimes useful, especially in large projects. This updates your local repo with any new branches that may have been created by others</em></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git checkout &lt;branch-name&gt;
</code></pre></div></div>

<h4 id="renaming-a-branch">Renaming a branch</h4>

<p>While on the branch you can change it’s name like so,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git branch -m &lt;new-branch-name&gt;
</code></pre></div></div>

<h4 id="deleting-branches">Deleting branches</h4>

<p>There are various ways to delete a branch, both a local copy and a remote copy.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git branch -d &lt;branch-name&gt;
git branch -D &lt;branch-name&gt;
git push origin --delete &lt;branch-name&gt;
git push origin :&lt;branch-name&gt;
</code></pre></div></div>

<p><em>Note: Deleting it locally does not “delete” the branch, it still exists on the remote server until you <code class="language-plaintext highlighter-rouge">push</code> your changes out, thread with caution.</em></p>

<h3 id="committing-amending-and-pushing-changes">Committing, Amending and Pushing changes</h3>

<p>Commits can be thought of as snapshots or milestones along the timeline of a Git project.</p>

<p>Used when you want to capture the state of changes to the project or mark milestones as the work evolves.</p>

<h4 id="adding-new-files">Adding new files</h4>

<p>Before there is anything to commit, you need to add the any changes or files to git. Essentially what this does is that it notifies git to “keep track” of changes to the file.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git add &lt;file-name&gt;
</code></pre></div></div>

<p>Add’s a single file by name</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git add . 
</code></pre></div></div>

<p>This adds every file change in current directory.</p>

<p>Key word here is <code class="language-plaintext highlighter-rouge">current</code> directory. If you have made a repo that has many parent and child folders and you make changes in multiple places then you either have to jump to each folder and run the above command or jump to the parent directory and add all.</p>

<h4 id="committing-changes">Committing changes</h4>

<p>When you have changes or have reached a point you want to “mark”, then its a good time to <code class="language-plaintext highlighter-rouge">commit</code> your changes after you have <a href="#adding-new-files">added</a> them.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git status
</code></pre></div></div>

<p>Will show you all changes ready to be committed</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git commit –m “your descriptive but brief commit message”
git commit –am “your descriptive but brief commit message” 
</code></pre></div></div>

<p>If file has already been <a href="#adding-new-files">staged</a>, you can skip the <code class="language-plaintext highlighter-rouge">add</code> commands and just use the <code class="language-plaintext highlighter-rouge">-am</code> flag, this is a short cut to both <code class="language-plaintext highlighter-rouge">add</code> the file and add a commit message as above.</p>

<h4 id="amending-commits">Amending commits</h4>

<p>There sometime is the need to amend a most recent commit e.g. You had committed your changes but added a new change that you want to reflect as part of the previous commit set. To do so you can:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git commit --amend
</code></pre></div></div>

<p>To add the new change to the last commit</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git commit --amend -m "an updated commit message” 
</code></pre></div></div>

<p>To both add the new change and also update the commit message. For example you notice a typo, happens to the best of us. 🙃</p>

<h3 id="changing-committed-files">Changing committed files</h3>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git add &lt;the-file&gt;
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git commit --amend --no-edit
</code></pre></div></div>

<blockquote>
  <p>🔥 Don’t amend public commits, avoid amending a commit that other developers have based their work on, do so only on your local branch/commits.</p>
</blockquote>

<h3 id="pushing-changes-to-remote">Pushing changes to remote</h3>

<p>When happy with your changes, you can make it public or visible to other collaborators by placing it in the central location with the below commands.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push
</code></pre></div></div>

<h3 id="merging-rebasing-and-reverting">Merging, Rebasing and Reverting</h3>

<p>There are time when you need to lump things together, combining changes from more than one branch.</p>

<p>Git merge is used to combine changes from two or more branches into a single branch.</p>

<p>Git rebase is used to incorporate changes from one branch into another by rewriting the commit history.</p>

<p>These feature can be very helpful in keeping things organised or help you separate/chunk your work in more that one branch then bring them all together in one branch.</p>

<h4 id="merging">Merging</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git checkout &lt;branch name&gt;
git merge main
git merge &lt;branch name&gt; main
</code></pre></div></div>

<p>Options include <code class="language-plaintext highlighter-rouge">--squash</code>, <code class="language-plaintext highlighter-rouge">--abort</code>, <code class="language-plaintext highlighter-rouge">--quit</code>, <code class="language-plaintext highlighter-rouge">-s [our]</code> etc.</p>

<h4 id="rebasing">Rebasing</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git checkout &lt;branchname&gt;
git rebase main
</code></pre></div></div>

<blockquote>
  <p>The golden rule of git rebase is to never use it on public branches</p>
</blockquote>

<p>You can look at a <code class="language-plaintext highlighter-rouge">merge</code> as combining two repos together, sorting out the difference between them and a <code class="language-plaintext highlighter-rouge">rebase</code> as adding one repo right on top of the other.</p>

<p>Git has a nice documentation called <a href="https://git-scm.com/book/en/v2/Git-Branching-Rebasing">Git Branching - Rebasing</a> that breaks it down in detail. Check it out if you need more clarity.</p>

<h4 id="squashing">Squashing</h4>

<p>This is another feature that allows you group multiple commits into one. If you have multiple small changes committed and want to push them out together then <code class="language-plaintext highlighter-rouge">squash</code> them.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git log --oneline
git rebase -i HEAD~N
git merge --squash &lt;branch name&gt; (then commit)
</code></pre></div></div>

<blockquote>
  <p>ℹ️ Very useful for tidying up local commits before a milestone push.</p>
</blockquote>

<p><em>🔥 Note: Try to avoid squashing too many changes into one push that it become one large commit when its review time. Everything in moderation.</em></p>

<h4 id="reverting">Reverting</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git revert --&lt;hard|soft|mixed&gt; &lt;commit-id&gt;
</code></pre></div></div>

<h3 id="pulling-searching-and-aliases">Pulling, Searching and Aliases</h3>

<p>Git pull is used to fetch and download content from a remote repository, updating the local repository to match that content.</p>

<p>Git aliases can shorten common commands and make it easy for you to remember, just try not to go overboard.</p>

<h4 id="pulling">Pulling</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git pull &lt;remote&gt;
git pull --rebase &lt;remote&gt;
</code></pre></div></div>

<blockquote>
  <p>Used to ensure a linear history by preventing unnecessary merge commits.</p>
</blockquote>

<h4 id="searching">Searching</h4>

<p>You can look into your git repo or history to search for information about past commits, branches etc.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git grep &lt;text&gt; 
</code></pre></div></div>

<p>This will look through files</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git log &lt;options&gt; 
</code></pre></div></div>

<p>This will show your commits</p>

<h4 id="aliases">Aliases</h4>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git config --global alias.&lt;name&gt; ‘&lt;git subcommand options&gt;’
git config –e 
</code></pre></div></div>

<p>To open your default editor</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git config --list
</code></pre></div></div>

<p>To show your git configuration and all the crazy aliases you have set, and the one you had forgotten about 🙃.</p>

<h3 id="next-steps">Next Steps</h3>

<p>Git is really powerful and has lots of features, it can sometimes feel overwhelming but practicing one feature at a time is the way to go, you can try out most commands locally.</p>

<h3 id="for-more-adventures">For More Adventures</h3>

<p>Any of the below commands in your terminal will provide you with lots of git related information. Comes in handy when you quickly want to verify a command or look up a concept.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git –help 
git help -a
git help -g
</code></pre></div></div>

<p>These will show you lots of other options you can have a play with.</p>

<h3 id="practice-practice-practice">Practice, practice, practice</h3>

<p>Some great places to look to for deeper learning</p>

<ul>
  <li><a href="https://git-scm.com/doc">Git documentation</a></li>
  <li><a href="https://cbx33.github.io/gitt/intro.html">Git In The Trenches</a></li>
  <li><a href="#for-more-adventures">For More Adventures</a> section commands</li>
</ul>

<p>FYI don’t get budged down with too much git detail, majority of the time the common commands will be more than enough for your daily work, having good knowledge of git, or what it can do, comes in handy when those edge cases crop up, usually when working with large teams or on a very active repo with many developers pushing changes near simultaneously.</p>

<p>These days however, most of our IDE’s come baked with lots of git  capabilities via plugins and extensions. You just need to install one if not already and you’re good-to-go.</p>]]></content><author><name>Felix Eyetan</name></author><category term="DevOps" /><summary type="html"><![CDATA[Assumptions]]></summary></entry><entry><title type="html">Peer reviews and why we need them</title><link href="https://madjava.github.io/blogs/2025/05/01/peer-reviews.html" rel="alternate" type="text/html" title="Peer reviews and why we need them" /><published>2025-05-01T00:00:00+00:00</published><updated>2025-05-01T00:00:00+00:00</updated><id>https://madjava.github.io/blogs/2025/05/01/peer-reviews</id><content type="html" xml:base="https://madjava.github.io/blogs/2025/05/01/peer-reviews.html"><![CDATA[<p>Code reviews are methodical assessments of code designed to identify bugs or errors, increase code quality, and help developers and engineers learn the source code.</p>

<p>PRs can also serve as a learning tool or a means of documentation. As not everyone in working on the same Initiative or deliverables at the same time, the opportunity to review another team members code give you the opportunity to be in the know of whats happening on the project.</p>

<h2 id="effective-peer-review">Effective Peer Review</h2>

<p>Below are some ideas to explore in your professional journey when working with a group of engineers or collaborating with some one on a body of work. These ideas are based on my experiences on various projects, past and present, and i hope you would find some of these ideas helpful on your projects.</p>

<h3 id="1-keep-prs-small-limit-the-code-to-one-cohesive-change">1. Keep PRs small, limit the code to one cohesive change</h3>

<p>Short pull requests (or PRs) are much simpler to review than long PRs. Try to break up large features or changes into multiple smaller PRs, more bugs and issues slip through on longer PRs due to reviewer fatigue. Also bigger PR longer time to be reviewed. Best to get small changes out than one giant change.</p>

<h3 id="2-follow-consistent-code-style">2. Follow consistent code style</h3>

<p>Following specific guidelines will allow your reviewers to focus on the substance of your change rather than superficial issues - haggling over whitespaces, funky indentations, style or format of function names is not a great use of anyone’s time.</p>

<h3 id="2-make-your-code-self-documenting">2. Make your code self-documenting</h3>

<p>Think about your variables, function or resource names, signatures, modules, etc. Make sure they accurately describe their contents and purpose. Using good naming convention can make your code substantially easier for your reviewers to understand. Whether it’s IaC in Terraform or a feature in Java or NodeJS. Principles remain the same.</p>

<h3 id="3-document-complex-parts-of-the-code-with-comments-that-show-your-intent-as-an-engineer">3. Document complex parts of the code with comments that show your intent as an engineer</h3>

<p>In those cases when it’s not possible to write self-documenting code, it is sometimes complicated or hard to follow just by reading it, a few short comments describing how the code works and why it is the way it is can help, even if its eventually removed after reviews and before your merge.</p>

<p>Caution though not to over load your code with comments, this is where <code class="language-plaintext highlighter-rouge">README</code> files in your project can come in handy, especially if you introduced significant change to the project or functionality.</p>

<h3 id="4-give-your-pr-a-good-title-and-pr-description">4. Give your PR a good title and PR description</h3>

<p>Be specific, describe both the reason for the change and the way this change achieves a goal. Be clear, but not overly verbose. A clear description helps your reviewers gain context on what you’re looking to achieve.</p>

<h3 id="5-draw-attention-to-sections-of-interest">5. Draw attention to sections of interest</h3>

<p>Provide pointers as comments for sections of the code that could use particular attention from the reviewer. Dropping comments on your own PRs can allow you to provide justification for changes in-line. This is helpful when you have thoughts that you need to share but that wouldn’t be useful as a persisting code comment, describing the reasoning behind an approach can sometimes make more sense as a comment than as a comment in the source code. Super useful as well if you’d like other opinions on a particular implementation.</p>

<h3 id="5-request-reviews-from-the-right-people">5. Request reviews from the right people</h3>

<p>Sometimes, asking for reviews from people with the right context, experience or knowledge of the project can be helpful.</p>

<p>General rule of thumbs is that any member of the team should be able to review, but honestly i’ve been in situations where i had to pull in specific team members on an issue due to experience in that topic or feature. Value every review though.</p>

<h3 id="6-indicate-when-your-code-is-ready-for-review">6. Indicate when your code is ready for review</h3>

<p>You can save your reviewers’ time and yourself from frustration by marking your PRs as a <code class="language-plaintext highlighter-rouge">Draft</code> while you are still working on it and only tagging people or requesting a review when your code is ready for a look.</p>

<p>This saves a team member having to “down tools” to review your work and also “comments” about things you know you are going to implement anyways but not gotten to it yet.</p>

<p>Always nice to start out in <code class="language-plaintext highlighter-rouge">Draft</code> mode then when ready for first review switch to <code class="language-plaintext highlighter-rouge">Ready for Review</code>.</p>

<h3 id="7-ask-for-the-feedback-youre-looking-for">7. Ask for the feedback you’re looking for</h3>

<p>It can be helpful to write your reviewers a little note as a comment on the PR pointing out areas of uncertainty you have, requesting specific types of suggestions, or waving them off of something if you have broken a standard pattern for a valid reason.</p>

<p>Leverage comment on your PR at to draw attention to point for feedback.</p>

<h2 id="general-standards-best-practice">General Standards, Best practice</h2>

<h3 id="change-requests">Change Requests</h3>

<p>Once you request a change i.e. <code class="language-plaintext highlighter-rouge">Block</code> a PR from merge, “You own it”, reach out if no updates after a while or help the engineer with pointers especially if they are struggling. The time taken to update the PR, especially if not a very complex issue/resolution is requested, can be an indication that the engineer is struggling in implementing the requested change.</p>

<p>I have experienced a situation where a team member requested a change, essentially <code class="language-plaintext highlighter-rouge">blocking</code> my PR but then went on leave without getting back to review changes before heading out.</p>

<h3 id="professional-courtesy">Professional Courtesy</h3>

<p>Don’t merge until reviewers’ comments are clarified, where possible. If a colleague has made the effort to review and has asked some clarifying questions, just because you have the “required” number of approvals does not mean you totally ignore their question(s).</p>

<p>Do your best, and as a matter of courtesy, to either respond to the comment or reach out via Slack or whatever internal messaging channel is in use to chat about it.</p>

<h3 id="description-less-prs">Description-less PRs</h3>

<p>Engineers are sometimes in a hurry or maybe feel the change is a very small change and they can’t be bothered. This is not a good practice. At least add the link to the Jira ticket, if no ticket, there usually is one, then mention the incident or change request number or any other available tracking detail. If none of the above exist then state clearly the reason for the PR, there has to be one.</p>

<p>There are no “useless” descriptions either, your future self and other engineers, current and future will appreciate the effort.</p>

<h3 id="branch--pr-prefix">Branch / PR prefix</h3>

<p>Making it possible to find or reference changes when looking through your git history can be very helpful. Some ideas when creating your branch include:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">&lt;jira number&gt;-&lt;branch name&gt;</code></li>
  <li><code class="language-plaintext highlighter-rouge">&lt;issue number&gt;-&lt;branch name&gt;</code></li>
  <li><code class="language-plaintext highlighter-rouge">&lt;incident number&gt;-&lt;branch name&gt;</code></li>
  <li><code class="language-plaintext highlighter-rouge">&lt;change request number&gt;-&lt;branch name&gt;</code></li>
</ul>

<p>A colleague of mine uses <code class="language-plaintext highlighter-rouge">fix:</code> to indicate a fix or <code class="language-plaintext highlighter-rouge">feat:</code> to indicate a feature to help him differentiate what type of change when in.</p>

<p>If your organisation is not fussy about this or there isn’t a standard your team follows then i propose one of the above ideas.</p>

<p>It’s always best to avoid “floating” PR that make no sense 3 months later.</p>

<h3 id="leave-a-comment-on-the-jira-ticket-before-you-mark-is-as-done">Leave a comment on the Jira ticket before you mark is as “Done”</h3>

<p>If you are in a position where you can or are allowed to close Jira tickets, it’s good to be proactive, add a small comment when closing a ticket item.</p>

<p>Your Agile lead or Project manager will thank you for it. Useful details/information in your Jira ticket or GitHub project Issues before closing them can go a long in providing context to the wider team, external or interested parties who usually are nontechie’s folks.</p>

<h3 id="complete-your-reviews">Complete your reviews</h3>

<p>Because some other team member has approved a PR does not mean you should not complete your review especially if it’s a familiar code base or project.</p>

<p>I have noticed on projects i’ve worked on where some other engineer abandons his/her review just because more “senior” or “experienced” engineers have give it a thumbs up.</p>

<p>From experience they sometimes are wrong and sometimes miss details, usually because they usually are always “multitasking”, so many other “issues” needing their attention because of their experience.</p>

<p>If not for anything, try understand why that “senior” or “more experienced” engineer thought the PR is good-to-go. You can gain experience for next time on similar PRs, also you may just notice they have missed a point and your attention to detail prevented a bug making it’s way to production, especially if working on a full CI/CD project.</p>

<h3 id="patience-waiting-for-reviews">Patience, waiting for Reviews</h3>

<p>Sometimes waiting for a PR review can be nerve racking. If on a busy project or availability is limited due to holidays or absence, you’ll need to be patience and considerate when “pinging” others to to get some “eye’s on it”.</p>

<p>Some ideas i have used in the past, while i wait, is to “where” a different “hat” and look at my PR again as a “reviewer” or i ask myself “what can i improve on?”. I sometime find more things to do to improve what i thought was “ready for review”.</p>

<h3 id="have-a-thick-skin">Have a “thick” skin</h3>

<p>After all, you asked for it (joke), keep an open mind. Some colleagues don’t have filters and come at you quite bluntly, no “sugar coating”. Keep the end goal in mind, at least consider their point, sometimes they are actually right and sometimes not, always best to consider other ideas or thoughts, your end result will be much better and by thinking through it with other ideas in mind you may just learn something new as well.</p>]]></content><author><name>Felix Eyetan</name></author><category term="DevOps" /><summary type="html"><![CDATA[Code reviews are methodical assessments of code designed to identify bugs or errors, increase code quality, and help developers and engineers learn the source code.]]></summary></entry></feed>