<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Alek&#x27;s Blog - security</title>
    <subtitle>My Blog to share my knowledge</subtitle>
    <link rel="self" type="application/atom+xml" href="https://blog.none.at/categories/security/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blog.none.at"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-07-09T00:00:00+00:00</updated>
    <id>https://blog.none.at/categories/security/atom.xml</id>
    <entry xml:lang="en">
        <title>Sovereign-Cloud-Washing: Five Questions</title>
        <published>2026-07-09T00:00:00+00:00</published>
        <updated>2026-07-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-09-sovereign-cloud-washing/"/>
        <id>https://blog.none.at/blog/2026/2026-07-09-sovereign-cloud-washing/</id>
        
        <summary type="html">&lt;p&gt;“Sovereign cloud” is printed on marketing pages from AWS, Microsoft, Google, and a long list of
European providers alike. The label rarely comes with a definition, which makes it easy to satisfy
on paper and hard to verify in practice. I’ve put together five concrete questions, asked of the
claim itself instead of the label — enough to see, from several angles, what a provider actually
stands behind.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Who Has Access? Humans, Accounts, AI Agents</title>
        <published>2026-07-09T00:00:00+00:00</published>
        <updated>2026-07-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-09-sovereignty-access-model/"/>
        <id>https://blog.none.at/blog/2026/2026-07-09-sovereignty-access-model/</id>
        
        <summary type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-09-sovereign-cloud-washing&#x2F;&quot;&gt;Part 1&lt;&#x2F;a&gt; split the technology-supply-chain
question into two halves: what the platform is built on, and who — or what — actually has access to
it. &lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-09-sovereignty-technology-stack&#x2F;&quot;&gt;Part 2&lt;&#x2F;a&gt; answered the first half. This
post answers the second, using systems already built and operated for this blog rather than new
research — human access, service-account access, and (increasingly relevant) AI-agent access, all
checked against the same bar: is it documented, is it audited, and is it technically enforced or
just expected to be followed.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Legally vs. Technically Enforced</title>
        <published>2026-07-09T00:00:00+00:00</published>
        <updated>2026-07-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-09-sovereignty-enforcement-framework/"/>
        <id>https://blog.none.at/blog/2026/2026-07-09-sovereignty-enforcement-framework/</id>
        
        <summary type="html">&lt;p&gt;The same distinction has come up three times already in this series without being named directly:
BYOK in &lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-09-sovereign-cloud-washing&#x2F;&quot;&gt;Part 1&lt;&#x2F;a&gt;, two vendors’ own statements in
&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-09-sovereignty-technology-stack&#x2F;&quot;&gt;Part 2&lt;&#x2F;a&gt;, and Kubernetes RBAC against a
written &lt;code&gt;CLAUDE.md&lt;&#x2F;code&gt; rule in &lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-09-sovereignty-access-model&#x2F;&quot;&gt;Part 3&lt;&#x2F;a&gt;. This post
makes it explicit, adds a third rung most sovereignty marketing doesn’t reach yet, and applies it
across everything the series has found so far — no new research, just naming a pattern that kept
repeating.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Can You Leave? Data Portability &amp; Egress</title>
        <published>2026-07-09T00:00:00+00:00</published>
        <updated>2026-07-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-09-sovereignty-exit-path/"/>
        <id>https://blog.none.at/blog/2026/2026-07-09-sovereignty-exit-path/</id>
        
        <summary type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-09-sovereign-cloud-washing&#x2F;&quot;&gt;Part 1&lt;&#x2F;a&gt; deliberately kept Question 4 — can you
leave — at the general level. This post is the deep-dive: concrete data-export
formats, API and query-language openness, and egress pricing already documented for AWS, GCP,
Azure, and OVH, plus new findings on how the five sovereignty offerings from
&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-09-sovereignty-technology-stack&#x2F;&quot;&gt;Part 2&lt;&#x2F;a&gt; actually hold up on exit.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Digital Sovereignty: The Complete Guide</title>
        <published>2026-07-09T00:00:00+00:00</published>
        <updated>2026-07-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-09-sovereignty-guide/"/>
        <id>https://blog.none.at/blog/2026/2026-07-09-sovereignty-guide/</id>
        
        <summary type="html">&lt;p&gt;This is the index and reading guide for a six-part series built around one idea: “sovereign cloud”
is a marketing label until it’s tested against something specific. Part 1 sets out five concrete
questions to test it against instead of taking the label at face value; Parts 2 through 6 are the
deep-dives that answer each one in turn — grounded, wherever possible, in research or systems
already published elsewhere on this blog rather than written fresh for the series.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>What Does It Cost to Leave — or Arrive?</title>
        <published>2026-07-09T00:00:00+00:00</published>
        <updated>2026-07-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-09-sovereignty-switching-cost/"/>
        <id>https://blog.none.at/blog/2026/2026-07-09-sovereignty-switching-cost/</id>
        
        <summary type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-09-sovereign-cloud-washing&#x2F;&quot;&gt;Part 1&lt;&#x2F;a&gt; deliberately kept Question 5 at the
general level too: on-prem is largely sovereign, but “engineering time re-architecting for a
new platform’s primitives, process changes… and a skills gap no one accounted for” apply whichever
direction you’re moving. This post is that deep-dive — the last of the five, using examples already
built and published rather than new claims about any provider.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Who Builds the Platform? Ownership vs. Stack</title>
        <published>2026-07-09T00:00:00+00:00</published>
        <updated>2026-07-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-09-sovereignty-technology-stack/"/>
        <id>https://blog.none.at/blog/2026/2026-07-09-sovereignty-technology-stack/</id>
        
        <summary type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-09-sovereign-cloud-washing&#x2F;&quot;&gt;Part 1&lt;&#x2F;a&gt; raised the technology-supply-chain
question with one case: Open Telekom Cloud, legally owned by Deutsche Telekom, running on a
Huawei-licensed platform. Five more prominent, more recent cases turn out to follow the same
pattern — checked here against primary sources, not just repeated from secondary coverage —
alongside three providers where ownership and technology stack come closer to aligning, each with
its own gaps left intact rather than smoothed over.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>k8s-scale-app-rs: Scale or Restart a Kubernetes Deployment from a CronJob</title>
        <published>2026-07-06T00:00:00+00:00</published>
        <updated>2026-07-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-06-k8s-scale-app-rs/"/>
        <id>https://blog.none.at/blog/2026/2026-07-06-k8s-scale-app-rs/</id>
        
        <content type="html" xml:base="https://blog.none.at/blog/2026/2026-07-06-k8s-scale-app-rs/">&lt;h2 id=&quot;tl-dr&quot;&gt;TL;DR&lt;a class=&quot;zola-anchor&quot; href=&quot;#tl-dr&quot; aria-label=&quot;Anchor link for: tl-dr&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git001&#x2F;k8s-scale-app-rs&quot;&gt;k8s-scale-app-rs&lt;&#x2F;a&gt; is a Rust CLI that does exactly one of two things and then exits:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;scale&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; — sets a Deployment’s replica count to a fixed value via the &lt;code&gt;deployments&#x2F;scale&lt;&#x2F;code&gt; subresource.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;restart&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; — patches the pod template’s &lt;code&gt;restartedAt&lt;&#x2F;code&gt; annotation, which is the same mechanism &lt;code&gt;kubectl rollout restart&lt;&#x2F;code&gt; uses.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Designed to run as a &lt;code&gt;CronJob&lt;&#x2F;code&gt;. Version 1.0.0 is published; container images and the Helm chart are on &lt;code&gt;ghcr.io&lt;&#x2F;code&gt;, signed with cosign (keyless via GitHub OIDC), and shipped with an SPDX SBOM plus SLSA build provenance.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-i-built-it&quot;&gt;Why I built it&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-i-built-it&quot; aria-label=&quot;Anchor link for: why-i-built-it&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The classic way to “run &lt;code&gt;kubectl scale&lt;&#x2F;code&gt; on a schedule in a cluster” is to put a &lt;code&gt;kubectl&lt;&#x2F;code&gt; binary into a Job image. That works, but it drags in a few things I did not want:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The full &lt;code&gt;kubectl&lt;&#x2F;code&gt; binary (about 50 MB stripped) for one API call.&lt;&#x2F;li&gt;
&lt;li&gt;A kubeconfig &#x2F; ServiceAccount plumbing that is broader than the one operation actually needs.&lt;&#x2F;li&gt;
&lt;li&gt;Enough YAML around the pod spec to hide the actual behavior behind a template.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A purpose-built tool is a natural fit for Rust here: a single self-contained binary — no OpenSSL, no runtime dependency beyond glibc and the CA trust store — and a ServiceAccount that only needs &lt;code&gt;deployments&#x2F;scale: patch&lt;&#x2F;code&gt;. That is what k8s-scale-app-rs is.&lt;&#x2F;p&gt;
&lt;p&gt;KEDA and Argo Workflows solve a related but different problem — reacting to events or orchestrating multi-step pipelines — not “flip a replica count or a restart annotation on a fixed schedule.” KEDA in particular has its own well-known scale-from-zero gap: a Prometheus-metric trigger can scale 1→N but not 0→1, because a Deployment at zero replicas emits no metric to react to (see &lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-06-02-llm-inference-on-ovh-observability&#x2F;#keda-autoscaling&quot;&gt;the LLM inference series&lt;&#x2F;a&gt; for the concrete failure mode). None of that machinery applies here — a CronJob calling a purpose-built binary on a fixed schedule has nothing to react to.&lt;&#x2F;p&gt;
&lt;p&gt;The same binary also covers restart. &lt;code&gt;kubectl rollout restart deployment&#x2F;foo&lt;&#x2F;code&gt; under the hood is one patch on &lt;code&gt;spec.template.metadata.annotations[&quot;kubectl.kubernetes.io&#x2F;restartedAt&quot;]&lt;&#x2F;code&gt;. Two subcommands, same binary, same image.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-it-does&quot;&gt;What it does&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-it-does&quot; aria-label=&quot;Anchor link for: what-it-does&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The CLI is two subcommands sharing common arguments:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;k8s-scale-app-rs scale   --deployment &amp;lt;NAME&amp;gt; --replicas &amp;lt;N&amp;gt; [--dry-run] [--extra-ca-bundle &amp;lt;PATH&amp;gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;k8s-scale-app-rs restart --deployment &amp;lt;NAME&amp;gt;                [--dry-run] [--extra-ca-bundle &amp;lt;PATH&amp;gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Configuration is via environment variables, overridable by CLI flags:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Flag&lt;&#x2F;th&gt;&lt;th&gt;ENV&lt;&#x2F;th&gt;&lt;th&gt;Subcommands&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;--deployment&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;K8S_SCALE_DEPLOYMENT&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;both&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;--namespace&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;K8S_SCALE_NAMESPACE&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;both&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;--replicas&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;K8S_SCALE_REPLICAS&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;scale&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;--dry-run&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;K8S_SCALE_DRY_RUN&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;both&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;--extra-ca-bundle&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;K8S_SCALE_EXTRA_CA_BUNDLE&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;both&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;The &lt;code&gt;--namespace&lt;&#x2F;code&gt; flag exists, but the CronJob does not hardcode it. Instead, the pod reads its own namespace from the Downward API and passes it through as an environment variable. That keeps the ServiceAccount’s Role safely namespace-scoped: the tool can only ever act on Deployments in the namespace where the CronJob itself runs. Not a general-purpose “scale anything anywhere” tool.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;design-highlights&quot;&gt;Design highlights&lt;a class=&quot;zola-anchor&quot; href=&quot;#design-highlights&quot; aria-label=&quot;Anchor link for: design-highlights&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;minimal-rbac-via-the-scale-subresource&quot;&gt;Minimal RBAC via the &lt;code&gt;scale&lt;&#x2F;code&gt; subresource&lt;a class=&quot;zola-anchor&quot; href=&quot;#minimal-rbac-via-the-scale-subresource&quot; aria-label=&quot;Anchor link for: minimal-rbac-via-the-scale-subresource&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Setting replicas does not need &lt;code&gt;patch&lt;&#x2F;code&gt; on the full Deployment. Kubernetes exposes &lt;code&gt;deployments&#x2F;scale&lt;&#x2F;code&gt; as a dedicated subresource:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;ules&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;piGroups&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;apps&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;esources&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;deployments&#x2F;scale&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;erbs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;patch&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;update&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That is all the scale mode needs. Restart mode does need &lt;code&gt;patch&lt;&#x2F;code&gt; on &lt;code&gt;deployments&lt;&#x2F;code&gt; itself (to update the pod template annotation), so the shipped Role covers both:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;piGroups&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;apps&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;esources&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;deployments&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;erbs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-separator&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;patch&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;patch&lt;&#x2F;code&gt; on the full Deployment is broader than &lt;code&gt;patch&lt;&#x2F;code&gt; on &lt;code&gt;deployments&#x2F;scale&lt;&#x2F;code&gt; — RBAC review at deploy time should factor that in when the CronJob is configured for restart mode.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;extra-ca-bundle-merged-into-the-trust-store&quot;&gt;Extra-CA bundle merged into the trust store&lt;a class=&quot;zola-anchor&quot; href=&quot;#extra-ca-bundle-merged-into-the-trust-store&quot; aria-label=&quot;Anchor link for: extra-ca-bundle-merged-into-the-trust-store&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The kube client uses the in-cluster CA from the ServiceAccount token secret automatically. For clusters whose API server certificate is signed by a corporate CA that is not in the SA-mounted &lt;code&gt;ca.crt&lt;&#x2F;code&gt;, &lt;code&gt;--extra-ca-bundle &amp;lt;path&amp;gt;&lt;&#x2F;code&gt; reads a PEM file (or a full chain of them) and appends every &lt;code&gt;CERTIFICATE&lt;&#x2F;code&gt; block to &lt;code&gt;kube::Config.root_cert&lt;&#x2F;code&gt;. Non-certificate blocks in the file are filtered out.&lt;&#x2F;p&gt;
&lt;p&gt;Rendered in Helm as an optional ConfigMap mount; in Kustomize as an opt-in Component. Neither path forces the mount when there is no corporate CA to add.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-rustls-0-23-cryptoprovider-gotcha&quot;&gt;The rustls 0.23 CryptoProvider gotcha&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-rustls-0-23-cryptoprovider-gotcha&quot; aria-label=&quot;Anchor link for: the-rustls-0-23-cryptoprovider-gotcha&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If you build against &lt;code&gt;kube-rs&lt;&#x2F;code&gt; with the &lt;code&gt;rustls-tls&lt;&#x2F;code&gt; feature on the current release, the binary compiles cleanly — and then panics at the first TLS handshake with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Could not automatically determine the process-level CryptoProvider from Rustls crate features&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;rustls&lt;&#x2F;code&gt; 0.23 no longer picks a crypto backend based on downstream feature flags. The application itself must call &lt;code&gt;rustls::crypto::ring::default_provider().install_default()&lt;&#x2F;code&gt; before any TLS work happens. In k8s-scale-app-rs this runs as the first step in &lt;code&gt;main()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Two notes for anyone hitting the same wall: the panic never fires at compile time, and no test caught it locally because integration tests without a cluster do not open a TLS connection. It only surfaces when the CronJob actually tries to reach the API server.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;two-deploy-paths-independent&quot;&gt;Two deploy paths, independent&lt;a class=&quot;zola-anchor&quot; href=&quot;#two-deploy-paths-independent&quot; aria-label=&quot;Anchor link for: two-deploy-paths-independent&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Helm and Kustomize both ship in the repo, and either can be used on its own:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Helm chart&lt;&#x2F;strong&gt; with &lt;code&gt;values-{dev,preprod,prod}.yaml&lt;&#x2F;code&gt;, a &lt;code&gt;mode: scale | restart&lt;&#x2F;code&gt; toggle that swaps the subcommand argument and drops the unused replicas env, and &lt;code&gt;serviceAccount.create&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;rbac.create&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;extraCA.enabled&lt;&#x2F;code&gt; toggles for the pieces that a given cluster may or may not need.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Kustomize&lt;&#x2F;strong&gt; with a base that has only the CronJob, plus three opt-in Components (&lt;code&gt;serviceaccount&#x2F;&lt;&#x2F;code&gt;, &lt;code&gt;rbac&#x2F;&lt;&#x2F;code&gt;, &lt;code&gt;extra-ca&#x2F;&lt;&#x2F;code&gt;) that overlays include as needed. Overlays under &lt;code&gt;overlays&#x2F;{dev,preprod,prod}&#x2F;&lt;&#x2F;code&gt; set namespace and image tag and a patch that touches only the fields that vary per stage.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;No Helm-inside-Kustomize glue, no Kustomize-on-Helm-render. Whichever tool matches an existing pipeline is the one to use.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;two-container-images&quot;&gt;Two container images&lt;a class=&quot;zola-anchor&quot; href=&quot;#two-container-images&quot; aria-label=&quot;Anchor link for: two-container-images&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The default image and a &lt;code&gt;-debug&lt;&#x2F;code&gt; variant, both built in the same GitHub Actions matrix — the
production&#x2F;&lt;code&gt;-debug&lt;&#x2F;code&gt; split itself is a general pattern, covered in more depth in
&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-01-k8s-openshift-bp-workloads&#x2F;#choose-your-base-image-carefully&quot;&gt;Part 2 of the K8s&#x2F;OpenShift Best Practices series&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;File&lt;&#x2F;th&gt;&lt;th&gt;Base&lt;&#x2F;th&gt;&lt;th&gt;Contents&lt;&#x2F;th&gt;&lt;th&gt;Approx. size&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Containerfile&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;registry.access.redhat.com&#x2F;ubi10&#x2F;ubi-micro&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Binary + CA trust store + &lt;code&gt;&#x2F;licenses&#x2F;&lt;&#x2F;code&gt;, no package manager&lt;&#x2F;td&gt;&lt;td&gt;≈35 MB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;Containerfile.debug&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;registry.access.redhat.com&#x2F;ubi10&#x2F;ubi-minimal&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Everything above + &lt;code&gt;bash&lt;&#x2F;code&gt;, &lt;code&gt;curl&lt;&#x2F;code&gt;, &lt;code&gt;bind-utils&lt;&#x2F;code&gt; (&lt;code&gt;dig&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;td&gt;≈115 MB&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;code&gt;ubi10-micro&lt;&#x2F;code&gt; is not fully distroless in the Google sense — bash and coreutils are still there — but it has no package manager and no network tools, which fits the pod’s actual operational surface for a scheduled scale or restart call. The &lt;code&gt;-debug&lt;&#x2F;code&gt; variant exists for the day a pod loops in &lt;code&gt;ImagePullBackOff&lt;&#x2F;code&gt; or a network policy silently drops the API-server traffic and someone needs to &lt;code&gt;kubectl exec&lt;&#x2F;code&gt; in with tools to check.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;why-ubi10&quot;&gt;Why UBI10&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-ubi10&quot; aria-label=&quot;Anchor link for: why-ubi10&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The base itself, not just the two variants built from it, was a deliberate choice. I went with
Red Hat’s UBI over an Alpine or a generic Docker Hub base image for one reason: it gives the
image a level of maintenance stability I don’t have to police myself — CVE scanning and rebuilds
are Red Hat’s job, not something I track on my own. That comes with a tradeoff worth stating
plainly: UBI is not “digitally sovereign” in the sense the upcoming Digital Sovereignty in
Practice series covers — it is a US vendor’s supply chain, the same as pulling from Docker Hub
or almost any other public registry would be. I did not find a base that solved that concern
without giving up the maintenance guarantees I wanted, so UBI10 here is a compromise I made
deliberately, not a claim that the underlying problem is solved.&lt;&#x2F;p&gt;
&lt;p&gt;Both images ship an aggregated &lt;code&gt;&#x2F;licenses&#x2F;LICENSES.txt&lt;&#x2F;code&gt; bundled with &lt;code&gt;cargo-about&lt;&#x2F;code&gt; during the container build, generated from a whitelist of accepted SPDX identifiers. A new dependency that pulls in an unfamiliar license fails the container build on purpose.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;supply-chain&quot;&gt;Supply chain&lt;a class=&quot;zola-anchor&quot; href=&quot;#supply-chain&quot; aria-label=&quot;Anchor link for: supply-chain&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git001&#x2F;k8s-scale-app-rs&#x2F;blob&#x2F;main&#x2F;.github&#x2F;workflows&#x2F;build-publish.yaml&quot;&gt;build-publish workflow&lt;&#x2F;a&gt; runs three jobs on every push, plus a release job on tag pushes:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;test&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; — &lt;code&gt;cargo fmt --check&lt;&#x2F;code&gt;, &lt;code&gt;cargo clippy -D warnings&lt;&#x2F;code&gt;, &lt;code&gt;cargo test --release&lt;&#x2F;code&gt;. Cluster tests auto-skip in CI (no &lt;code&gt;KUBECONFIG&lt;&#x2F;code&gt;, no in-cluster SA token).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;build-image&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; — matrix over &lt;code&gt;Containerfile&lt;&#x2F;code&gt; and &lt;code&gt;Containerfile.debug&lt;&#x2F;code&gt;. Each variant is built with buildx, pushed to &lt;code&gt;ghcr.io&#x2F;git001&#x2F;k8s-scale-app-rs&lt;&#x2F;code&gt;, smoke-tested (&lt;code&gt;--version&lt;&#x2F;code&gt;, &lt;code&gt;scale --help&lt;&#x2F;code&gt;, &lt;code&gt;restart --help&lt;&#x2F;code&gt;), then:
&lt;ul&gt;
&lt;li&gt;signed with &lt;strong&gt;cosign keyless&lt;&#x2F;strong&gt; via the GitHub OIDC token (no key management — Fulcio issues a short-lived certificate, the signature is logged to Rekor);&lt;&#x2F;li&gt;
&lt;li&gt;has an &lt;strong&gt;SPDX-JSON SBOM&lt;&#x2F;strong&gt; generated with syft and attached via &lt;code&gt;cosign attest --type spdxjson&lt;&#x2F;code&gt;;&lt;&#x2F;li&gt;
&lt;li&gt;has &lt;strong&gt;SLSA build provenance&lt;&#x2F;strong&gt; pushed with &lt;code&gt;actions&#x2F;attest-build-provenance&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;publish-chart&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; — &lt;code&gt;helm lint&lt;&#x2F;code&gt; and &lt;code&gt;helm package&lt;&#x2F;code&gt; on every push; OCI push to &lt;code&gt;oci:&#x2F;&#x2F;ghcr.io&#x2F;git001&#x2F;charts&#x2F;k8s-scale-app-rs&lt;&#x2F;code&gt;, plus cosign sign and SLSA provenance only on tag events (avoids overwrite conflicts on GHCR-immutable tags).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;release&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; (tag events only) — creates the GitHub Release with auto-generated notes from commits since the previous tag, attaches the packaged chart &lt;code&gt;.tgz&lt;&#x2F;code&gt; as an asset, and prepends the release body with pull and verify snippets.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;All of that runs with &lt;code&gt;permissions: contents:read, packages:write, id-token:write, attestations:write&lt;&#x2F;code&gt; — the minimum needed for OIDC-based signing plus attestation upload.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;verifying-a-published-image&quot;&gt;Verifying a published image&lt;a class=&quot;zola-anchor&quot; href=&quot;#verifying-a-published-image&quot; aria-label=&quot;Anchor link for: verifying-a-published-image&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A consumer that wants to check what came out of that pipeline needs cosign v2:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;IMG&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;g&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;g&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;l&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;v&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;IDENTITY&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;^https:&#x2F;&#x2F;github.com&#x2F;git001&#x2F;k8s-scale-app-rs&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;ISSUER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;g&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;u&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;u&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cosign&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; verify&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-certificate-identity-regexp&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;IDENTITY&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-certificate-oidc-issuer&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;ISSUER&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;IMG&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cosign&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; verify-attestation&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-type&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; spdxjson&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-certificate-identity-regexp&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;IDENTITY&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-certificate-oidc-issuer&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;ISSUER&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;IMG&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cosign&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; verify-attestation&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-type&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; slsaprovenance&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-certificate-identity-regexp&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;IDENTITY&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-certificate-oidc-issuer&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;ISSUER&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other z-variable&quot;&gt;IMG&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For enforcement inside the cluster, a cosign-aware admission controller — &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;kyverno.io&#x2F;&quot;&gt;Kyverno&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sigstore&#x2F;policy-controller&quot;&gt;Sigstore policy-controller&lt;&#x2F;a&gt;, or &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sse-secure-systems.github.io&#x2F;connaisseur&#x2F;&quot;&gt;Connaisseur&lt;&#x2F;a&gt; — can turn the signature into a hard gate that rejects any pod trying to pull an image that was not produced by exactly this workflow. That is a separate deployment concern; the tool repo does not ship the policy itself.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mirroring-the-image-into-another-registry&quot;&gt;Mirroring the image into another registry&lt;a class=&quot;zola-anchor&quot; href=&quot;#mirroring-the-image-into-another-registry&quot; aria-label=&quot;Anchor link for: mirroring-the-image-into-another-registry&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Verifying a signature only works if the signature actually travels with the image. Not every &lt;code&gt;docker pull &amp;amp;&amp;amp; docker push&lt;&#x2F;code&gt;-style mirroring tool preserves it — some tools do, some quietly drop it, and one (&lt;code&gt;oc-mirror v2&lt;&#x2F;code&gt;) solves a related but entirely different signature problem. I wrote up a full, sourced comparison — &lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-06-mirroring-signed-images-private-registry&#x2F;&quot;&gt;Which Tool Mirrors a Cosign-Signed Image into a Private Registry?&lt;&#x2F;a&gt; — with &lt;code&gt;regctl&lt;&#x2F;code&gt; coming out as the most complete option for this specific image.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;code-and-repository&quot;&gt;Code and repository&lt;a class=&quot;zola-anchor&quot; href=&quot;#code-and-repository&quot; aria-label=&quot;Anchor link for: code-and-repository&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Repository: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git001&#x2F;k8s-scale-app-rs&quot;&gt;k8s-scale-app-rs on GitHub&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Container images: &lt;code&gt;ghcr.io&#x2F;git001&#x2F;k8s-scale-app-rs:v1.0.0&lt;&#x2F;code&gt; and &lt;code&gt;ghcr.io&#x2F;git001&#x2F;k8s-scale-app-rs:v1.0.0-debug&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Helm chart: &lt;code&gt;oci:&#x2F;&#x2F;ghcr.io&#x2F;git001&#x2F;charts&#x2F;k8s-scale-app-rs:1.0.0&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Feedback and PRs welcome.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Which Tool Mirrors a Cosign-Signed Image into a Private Registry?</title>
        <published>2026-07-06T00:00:00+00:00</published>
        <updated>2026-07-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-06-mirroring-signed-images-private-registry/"/>
        <id>https://blog.none.at/blog/2026/2026-07-06-mirroring-signed-images-private-registry/</id>
        
        <content type="html" xml:base="https://blog.none.at/blog/2026/2026-07-06-mirroring-signed-images-private-registry/">&lt;h2 id=&quot;tl-dr&quot;&gt;TL;DR&lt;a class=&quot;zola-anchor&quot; href=&quot;#tl-dr&quot; aria-label=&quot;Anchor link for: tl-dr&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;regctl&lt;&#x2F;code&gt; is the most complete option — it exposes the legacy tag-based signature scheme and the
modern OCI 1.1 referrers API as two separate, explicit flags. &lt;code&gt;oras cp -r&lt;&#x2F;code&gt; is the second choice,
and the tool cosign’s own project points to now that &lt;code&gt;cosign copy&lt;&#x2F;code&gt; is deprecated. &lt;code&gt;oc-mirror v2&lt;&#x2F;code&gt;
looks like it should be on this list but actually solves a different, unrelated signature problem.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The problem&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-problem&quot; aria-label=&quot;Anchor link for: the-problem&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Verifying a signature only works if the signature actually travels with the image. Anyone mirroring
a Cosign-signed image into a private or air-gapped registry needs the copy step itself to carry the
signature along, not just the layers — and that is not automatic. Some tools drop it silently, some
need a config flag turned on first, and one widely-used tool solves a related but entirely different
problem. &lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-06-k8s-scale-app-rs&#x2F;&quot;&gt;k8s-scale-app-rs&lt;&#x2F;a&gt; is the worked example
throughout this post — its own container images are signed keylessly with cosign, carry an SBOM and
SLSA build provenance, and its &lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-06-k8s-scale-app-rs&#x2F;#verifying-a-published-image&quot;&gt;“Verifying a published image”&lt;&#x2F;a&gt;
section shows what verification actually checks. This post is about what happens &lt;em&gt;before&lt;&#x2F;em&gt;
verification: getting the signature into the registry the verifier will actually query.&lt;&#x2F;p&gt;
&lt;p&gt;A short, sourced comparison, checked directly against each project’s docs&#x2F;source (as of July 2026):&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-naming-trap-worth-knowing-first&quot;&gt;A naming trap worth knowing first&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-naming-trap-worth-knowing-first&quot; aria-label=&quot;Anchor link for: a-naming-trap-worth-knowing-first&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Red Hat’s &lt;code&gt;oc-mirror v2&lt;&#x2F;code&gt; — the tool for mirroring into disconnected OpenShift installs — has its
own &lt;code&gt;--secure-policy&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;--remove-signatures&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;--registries.d&lt;&#x2F;code&gt; flags, but they implement Red Hat’s
older “simple signing” scheme: a &lt;code&gt;policy.json&lt;&#x2F;code&gt; plus GPG keys plus an external &lt;code&gt;sigstore:&lt;&#x2F;code&gt; URL (e.g.
&lt;code&gt;mirror.openshift.com&#x2F;pub&#x2F;openshift-v4&#x2F;signatures&lt;&#x2F;code&gt; for OpenShift release images). That predates,
and has nothing to do with, the CNCF Sigstore project this post’s cosign workflow uses — same word,
unrelated mechanism. &lt;code&gt;oc-mirror v2&lt;&#x2F;code&gt; went GA in OpenShift 4.18 (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.redhat.com&#x2F;en&#x2F;documentation&#x2F;openshift_container_platform&#x2F;4.18&#x2F;html&#x2F;release_notes&#x2F;ocp-4-18-release-notes&quot;&gt;release
notes&lt;&#x2F;a&gt;),
but its &lt;code&gt;ImageSetConfiguration&lt;&#x2F;code&gt; API is still &lt;code&gt;v2alpha1&lt;&#x2F;code&gt;, and none of Red Hat’s own walkthroughs for
it touch Cosign-style signatures at all.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tool-comparison&quot;&gt;Tool comparison&lt;a class=&quot;zola-anchor&quot; href=&quot;#tool-comparison&quot; aria-label=&quot;Anchor link for: tool-comparison&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Tool&lt;&#x2F;th&gt;&lt;th&gt;Legacy tag-based signature (&lt;code&gt;sha256-&amp;lt;digest&amp;gt;.sig&lt;&#x2F;code&gt;)&lt;&#x2F;th&gt;&lt;th&gt;OCI 1.1 referrers (modern Cosign&#x2F;SBOM&#x2F;attestations)&lt;&#x2F;th&gt;&lt;th&gt;Note&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;regctl.regclient.org&#x2F;cli&#x2F;regctl&#x2F;image&#x2F;copy&#x2F;&quot;&gt;&lt;code&gt;regctl image copy&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;--digest-tags&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;--referrers&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;only tool here with separate, explicit flags for both schemes&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;oras.land&#x2F;docs&#x2F;commands&#x2F;oras_cp&quot;&gt;&lt;code&gt;oras cp -r&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td&gt;via &lt;code&gt;-r&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;-r&lt;&#x2F;code&gt; (marked “Preview”)&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;--from&#x2F;to-distribution-spec&lt;&#x2F;code&gt; handles referrers-tag vs. referrers-API mismatches between registries&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;skopeo copy&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;opt-in&lt;&#x2F;td&gt;&lt;td&gt;not supported&lt;&#x2F;td&gt;&lt;td&gt;needs &lt;code&gt;use-sigstore-attachments: true&lt;&#x2F;code&gt; under the &lt;code&gt;default-docker&lt;&#x2F;code&gt; key in &lt;code&gt;registries.d&lt;&#x2F;code&gt;, on both source and destination&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Zot registry &lt;code&gt;sync&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;syncLegacyCosignTags&lt;&#x2F;code&gt; (default &lt;code&gt;true&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;&lt;td&gt;only with &lt;code&gt;preserveDigest: true&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;without &lt;code&gt;preserveDigest&lt;&#x2F;code&gt;, Zot re-encodes Docker-format images to OCI on sync, which changes the digest and detaches the signature&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;cosign copy&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;yes&lt;&#x2F;td&gt;&lt;td&gt;no&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;deprecated&lt;&#x2F;strong&gt; as of &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sigstore&#x2F;cosign&#x2F;pull&#x2F;4681&quot;&gt;sigstore&#x2F;cosign#4681&lt;&#x2F;a&gt; (merged 2026-02-04) — the tool itself now points to &lt;code&gt;oras copy -r&lt;&#x2F;code&gt; instead&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;crane copy&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;only incidentally, via &lt;code&gt;--all-tags&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;no&lt;&#x2F;td&gt;&lt;td&gt;plain manifest&#x2F;layer copier, no signature awareness at all&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Harbor replication&lt;&#x2F;td&gt;&lt;td&gt;per Harbor’s own docs, yes&lt;&#x2F;td&gt;&lt;td&gt;open gap (&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;goharbor&#x2F;harbor&#x2F;issues&#x2F;23210&quot;&gt;goharbor&#x2F;harbor#23210&lt;&#x2F;a&gt;)&lt;&#x2F;td&gt;&lt;td&gt;works for the legacy scheme; OCI 1.1 referrers replication is not yet reliable&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;code&gt;regctl&lt;&#x2F;code&gt; is the only tool in this comparison that exposes both signature schemes as distinct,
intentional flags rather than as a side effect of copying “everything.” For a registry pair that
already speaks the OCI 1.1 referrers API end to end, &lt;code&gt;oras cp -r&lt;&#x2F;code&gt; is the other option worth
checking — it’s what the cosign project’s own deprecation notice for &lt;code&gt;cosign copy&lt;&#x2F;code&gt; points to.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example-mirroring-with-regctl&quot;&gt;Example: mirroring with regctl&lt;a class=&quot;zola-anchor&quot; href=&quot;#example-mirroring-with-regctl&quot; aria-label=&quot;Anchor link for: example-mirroring-with-regctl&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Here is an example command to mirror &lt;code&gt;k8s-scale-app-rs&lt;&#x2F;code&gt; itself, signature included, using &lt;code&gt;regctl&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;regctl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; image&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; copy&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-digest-tags&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other&quot;&gt;-referrers&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  ghcr.io&#x2F;git001&#x2F;k8s-scale-app-rs:v1.0.0&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;  my-private-registry.example.com&#x2F;k8s-scale-app-rs:v1.0.0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;sources&quot;&gt;Sources&lt;a class=&quot;zola-anchor&quot; href=&quot;#sources&quot; aria-label=&quot;Anchor link for: sources&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sigstore&#x2F;cosign&#x2F;pull&#x2F;4681&quot;&gt;sigstore&#x2F;cosign PR #4681 — “Deprecate cosign copy”&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sigstore&#x2F;cosign&#x2F;issues&#x2F;4335&quot;&gt;sigstore&#x2F;cosign#4335 — Complete OCI 1.1 Referrers API Support Across All Cosign Commands&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sigstore&#x2F;cosign&#x2F;issues&#x2F;4564&quot;&gt;sigstore&#x2F;cosign#4564 — cosign verify fails after cosign copy (JFrog Artifactory)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;podman-container-tools&#x2F;skopeo&#x2F;issues&#x2F;2061&quot;&gt;podman-container-tools&#x2F;skopeo#2061 — sigstore signature copying and &lt;code&gt;use-sigstore-attachments&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;regctl.regclient.org&#x2F;cli&#x2F;regctl&#x2F;image&#x2F;copy&#x2F;&quot;&gt;regctl &lt;code&gt;image copy&lt;&#x2F;code&gt; reference&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;oras.land&#x2F;docs&#x2F;commands&#x2F;oras_cp&quot;&gt;oras &lt;code&gt;cp&lt;&#x2F;code&gt; command reference&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;goharbor&#x2F;harbor&#x2F;issues&#x2F;23210&quot;&gt;goharbor&#x2F;harbor#23210 — OCI 1.1 referrers not replicated&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;zotregistry.dev&#x2F;v2.1.14&#x2F;articles&#x2F;mirroring&#x2F;&quot;&gt;Zot registry: mirroring&#x2F;sync documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.redhat.com&#x2F;en&#x2F;documentation&#x2F;openshift_container_platform&#x2F;4.18&#x2F;html&#x2F;release_notes&#x2F;ocp-4-18-release-notes&quot;&gt;OpenShift Container Platform 4.18 release notes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;openshift&#x2F;oc-mirror&#x2F;blob&#x2F;main&#x2F;docs&#x2F;features&#x2F;signature-verification.md&quot;&gt;openshift&#x2F;oc-mirror — signature-verification.md&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>K8s &amp; OpenShift: Compliance</title>
        <published>2026-07-01T00:00:00+00:00</published>
        <updated>2026-07-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-01-k8s-openshift-bp-compliance/"/>
        <id>https://blog.none.at/blog/2026/2026-07-01-k8s-openshift-bp-compliance/</id>
        
        <summary type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-01-k8s-openshift-bp-operations&#x2F;&quot;&gt;Part 6&lt;&#x2F;a&gt; covered the operational loop:
GitOps, observability, cost control, and upgrades. This final part maps the cluster configuration
covered throughout this series to the regulatory frameworks that require it — NIS2, DORA,
PCI-DSS, HIPAA, and the Cyber Resilience Act (CRA) — and covers the two topics that compliance
work adds on top of security: audit logging as evidence and log retention as a contractual
obligation.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>K8s &amp; OpenShift: Security</title>
        <published>2026-07-01T00:00:00+00:00</published>
        <updated>2026-07-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-01-k8s-openshift-bp-security/"/>
        <id>https://blog.none.at/blog/2026/2026-07-01-k8s-openshift-bp-security/</id>
        
        <summary type="html">&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-07-01-k8s-openshift-bp-scaling&#x2F;&quot;&gt;Part 4&lt;&#x2F;a&gt; covered scaling and resilience.
This part covers security — not as a checklist to complete before an audit, but as a set of
controls that reduce real attack surface and limit the blast radius when something goes wrong.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>What is Application Security</title>
        <published>2026-06-20T00:00:00+00:00</published>
        <updated>2026-06-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-06-19-ddos-application/"/>
        <id>https://blog.none.at/blog/2026/2026-06-19-ddos-application/</id>
        
        <summary type="html">&lt;p&gt;The third part of the (D)DoS series — but a step sideways: this post covers attacks at the Application layer that affect &lt;strong&gt;confidentiality and integrity&lt;&#x2F;strong&gt; rather than availability. SQL Injection, Log4Shell, and similar vulnerabilities have a different threat model than the DDoS attacks covered in the &lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-06-19-ddos-technical&#x2F;&quot;&gt;technical part&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>What is a (D)DoS - technical</title>
        <published>2026-06-20T00:00:00+00:00</published>
        <updated>2026-06-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-06-19-ddos-technical/"/>
        <id>https://blog.none.at/blog/2026/2026-06-19-ddos-technical/</id>
        
        <summary type="html">&lt;p&gt;The technical follow-up to the &lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-06-19-ddos&#x2F;&quot;&gt;non-technical (D)DoS overview&lt;&#x2F;a&gt;. Covers Layer 3&#x2F;4 network floods (SYN, UDP, amplification), BGP hijacking, Layer 7 application DDoS, and operational resilience — all focused on availability.&lt;&#x2F;p&gt;
&lt;p&gt;Originally published at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.opensourcerers.org&#x2F;2024&#x2F;01&#x2F;22&#x2F;whats-a-ddos-distributed-denial-of-service-and-how-to-protect-against-such-an-attack-technical&#x2F;&quot;&gt;opensourcerers.org&lt;&#x2F;a&gt;; updated with current attack vectors and technologies.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>What is a (D)DoS</title>
        <published>2026-06-20T00:00:00+00:00</published>
        <updated>2026-06-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-06-19-ddos/"/>
        <id>https://blog.none.at/blog/2026/2026-06-19-ddos/</id>
        
        <summary type="html">&lt;p&gt;(D)DoS attacks are not just a technical problem — they operate at the Business, Social, and Informational level as well. This post covers the non-technical dimensions; the &lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-06-19-ddos-technical&#x2F;&quot;&gt;technical follow-up&lt;&#x2F;a&gt; covers Layer 3&#x2F;4 network floods, BGP hijacking, TLS handshake attacks, Layer 7 application DDoS, and operational resilience.&lt;&#x2F;p&gt;
&lt;p&gt;Originally published at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.opensourcerers.org&#x2F;2023&#x2F;11&#x2F;27&#x2F;whats-a-ddos-and-how-to-protect-against-such-an-attack-non-technical&#x2F;&quot;&gt;opensourcerers.org&lt;&#x2F;a&gt;; updated with current examples and expanded framing.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>(D)DoS and Application Security: The Complete Guide</title>
        <published>2026-06-19T00:00:00+00:00</published>
        <updated>2026-06-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-06-19-ddos-guide/"/>
        <id>https://blog.none.at/blog/2026/2026-06-19-ddos-guide/</id>
        
        <summary type="html">&lt;p&gt;This is the index and reading guide for a three-part series on denial-of-service and application
security. The first two parts cover &lt;strong&gt;availability&lt;&#x2F;strong&gt; attacks — a service being made unreachable or
unusable — at levels most people don’t associate with the term “DDoS”: the business level (losing
the people who run the service), the social level (manipulating the humans behind it), the
informational level (reputational disruption), and finally the technical level most readers expect
(network floods, BGP hijacking, Layer 7 exhaustion). The third part is a deliberate step sideways,
into application-layer attacks — SQL Injection, Log4Shell, the OWASP Top 10 — that threaten
&lt;strong&gt;confidentiality and integrity&lt;&#x2F;strong&gt; instead of availability.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Elasticsearch vs. OpenSearch vs. Loki vs. Quickwit vs. ClickHouse: Security &amp; Compliance</title>
        <published>2026-05-14T00:00:00+00:00</published>
        <updated>2026-06-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-05-14-es-os-loki-quickwit-clickhouse-security/"/>
        <id>https://blog.none.at/blog/2026/2026-05-14-es-os-loki-quickwit-clickhouse-security/</id>
        
        <summary type="html">&lt;p&gt;Access control, encryption, and immutability requirements often determine whether a log
archive can be used for compliance purposes — and the five systems differ substantially in
what they enforce natively versus what must be delegated to infrastructure.&lt;&#x2F;p&gt;
&lt;p&gt;This is Part 3 of a five-part series.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Full guide:&lt;&#x2F;strong&gt; &lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-05-14-es-os-loki-quickwit-clickhouse-guide&#x2F;&quot;&gt;Elasticsearch vs. OpenSearch vs. Loki vs. Quickwit vs. ClickHouse: The Complete Guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-05-14-es-os-loki-quickwit-clickhouse&#x2F;&quot;&gt;Part 1 — Comparison:&lt;&#x2F;a&gt; Storage tiering, compression, resource consumption, query languages, SaaS options&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-05-14-es-os-loki-quickwit-clickhouse-operations&#x2F;&quot;&gt;Part 2 — Operations:&lt;&#x2F;a&gt; Setup, ingest pipeline, ECS vs. OTel, backup &amp;amp; DR, observability, alerting&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Part 3 — Security &amp;amp; Compliance — this post:&lt;&#x2F;strong&gt; Encryption, RBAC, WORM &#x2F; S3 Object Lock&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-05-14-es-os-loki-quickwit-clickhouse-ux&#x2F;&quot;&gt;Part 4 — UX, Dashboards &amp;amp; Alerts:&lt;&#x2F;a&gt; UI layers, log search UX, cold-tier query behaviour, dashboard building, sharing, alerting&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.none.at&#x2F;blog&#x2F;2026&#x2F;2026-05-14-es-os-loki-quickwit-clickhouse-usecases&#x2F;&quot;&gt;Part 5 — Use Case:&lt;&#x2F;a&gt; Vector, Istio&#x2F;Envoy, nginx, Java on OVH MKS — complete ClickHouse ingestion setup and monthly awffull report&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;</summary>
        
    </entry>
</feed>
