<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Caa on inetshell</title><link>https://inet.sh/en/tags/caa/</link><description>Recent content in Caa on inetshell</description><generator>Hugo</generator><language>en</language><lastBuildDate>Sat, 26 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://inet.sh/en/tags/caa/index.xml" rel="self" type="application/rss+xml"/><item><title>Google-managed certificate that never gets issued: CAA (pki.goog, letsencrypt.org), FAILED_NOT_VISIBLE and the right order</title><link>https://inet.sh/en/posts/gcp/google-managed-certificate-caa/</link><pubDate>Sat, 26 Sep 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/en/posts/gcp/google-managed-certificate-caa/</guid><description>The Google-managed certificate for an HTTPS load balancer sits in PROVISIONING for hours or drops to FAILED_NOT_VISIBLE or FAILED_CAA_FORBIDDEN. The three causes: DNS does not point to the load balancer IP yet, the certificate is not attached to a target proxy, or a CAA record in the zone does not authorize pki.goog or letsencrypt.org. How to check the status with gcloud, the correct CAA, and Certificate Manager with DNS authorization to issue before switching DNS.</description><content:encoded><![CDATA[<h2 id="tldr">TL;DR</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">example.com.   CAA 0 issue &#34;pki.goog&#34;
</span></span><span class="line"><span class="cl">example.com.   CAA 0 issue &#34;letsencrypt.org&#34;
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">gcloud compute ssl-certificates describe web-cert --global --format<span class="o">=</span><span class="s1">&#39;yaml(managed)&#39;</span>
</span></span><span class="line"><span class="cl"><span class="c1"># managed:</span>
</span></span><span class="line"><span class="cl"><span class="c1">#   domainStatus:</span>
</span></span><span class="line"><span class="cl"><span class="c1">#     www.example.com: PROVISIONING | ACTIVE | FAILED_NOT_VISIBLE | FAILED_CAA_FORBIDDEN | FAILED_CAA_CHECKING | FAILED_RATE_LIMITED</span>
</span></span><span class="line"><span class="cl"><span class="c1">#   status: PROVISIONING | ACTIVE</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>To reach <code>ACTIVE</code> three things must hold at once: the domain&rsquo;s <strong>A/AAAA</strong> points to the load balancer IP (and nothing else), the certificate is <strong>attached to a target proxy</strong> with its forwarding rule, and no <strong>CAA</strong> in the zone forbids Google&rsquo;s CAs. Then, up to <strong>60 minutes</strong>.</p>
<h2 id="why">Why</h2>
<p>Google issues managed certificates through <strong>Google Trust Services</strong> (<code>pki.goog</code>) or <strong>Let&rsquo;s Encrypt</strong>, and picks one or the other on each issuance or renewal. To validate the domain it runs an HTTP check against the IP the name resolves to, so until DNS points at the load balancer there is nothing to validate. And like any CA, it honors <strong>CAA</strong> records: if your zone says only <code>digicert.com</code> may issue (a typical corporate policy), Google cannot.</p>
<p>The statuses tell the story:</p>
<table>
  <thead>
      <tr>
          <th><code>domainStatus</code></th>
          <th>Cause</th>
          <th>What to do</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>PROVISIONING</code></td>
          <td>In progress</td>
          <td>Wait; past 60 minutes, check the items below</td>
      </tr>
      <tr>
          <td><code>FAILED_NOT_VISIBLE</code></td>
          <td>The name does not resolve to the load balancer IP, or the certificate is not attached to a target proxy</td>
          <td>Fix A/AAAA, attach the certificate, wait for propagation</td>
      </tr>
      <tr>
          <td><code>FAILED_CAA_CHECKING</code></td>
          <td>Google could not read the CAA records (unresponsive DNS, broken DNSSEC)</td>
          <td>Fix the zone</td>
      </tr>
      <tr>
          <td><code>FAILED_CAA_FORBIDDEN</code></td>
          <td>There is a CAA and it includes neither <code>pki.goog</code> nor <code>letsencrypt.org</code></td>
          <td>Add both records</td>
      </tr>
      <tr>
          <td><code>FAILED_RATE_LIMITED</code></td>
          <td>Too many issuance attempts</td>
          <td>Wait; do not recreate the certificate in a loop</td>
      </tr>
  </tbody>
</table>
<h2 id="the-right-caa">The right CAA</h2>
<p>With no CAA record at all, any CA may issue and Google works. If you have CAA (or your organization requires it), add <strong>both</strong> CAs:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">example.com.   CAA 0 issue &#34;pki.goog&#34;
</span></span><span class="line"><span class="cl">example.com.   CAA 0 issue &#34;letsencrypt.org&#34;
</span></span></code></pre></td></tr></table>
</div>
</div><p>Listing only one forces Google to always use that one; the documentation advises against it because a renewal may come out through the other. CAA records inherit downwards: a CAA on <code>example.com</code> covers <code>www.example.com</code> if the subdomain has none of its own.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">dig +short CAA example.com
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="certificate-manager-issue-before-switching-dns">Certificate Manager: issue before switching DNS</h2>
<p>With classic certificates (<code>compute ssl-certificates</code>) the domain must already point at the load balancer, which during a migration means a few minutes of broken HTTPS. <strong>Certificate Manager</strong> solves that with <strong>DNS authorization</strong>: you publish a validation CNAME and Google issues the certificate while traffic still flows to the old site.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">gcloud certificate-manager dns-authorizations create www-auth --domain<span class="o">=</span>www.example.com
</span></span><span class="line"><span class="cl">gcloud certificate-manager dns-authorizations describe www-auth --format<span class="o">=</span><span class="s1">&#39;yaml(dnsResourceRecord)&#39;</span>
</span></span><span class="line"><span class="cl"><span class="c1"># dnsResourceRecord: name: _acme-challenge.www.example.com. type: CNAME data: xxxx.authorize.certificatemanager.goog.</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># publish that CNAME in your zone and then:</span>
</span></span><span class="line"><span class="cl">gcloud certificate-manager certificates create www-cert <span class="se">\
</span></span></span><span class="line"><span class="cl"><span class="se"></span>  --domains<span class="o">=</span>www.example.com --dns-authorizations<span class="o">=</span>www-auth
</span></span><span class="line"><span class="cl">gcloud certificate-manager maps create web-map
</span></span><span class="line"><span class="cl">gcloud certificate-manager maps entries create www --map<span class="o">=</span>web-map --certificate<span class="o">=</span>www-cert --hostname<span class="o">=</span>www.example.com
</span></span><span class="line"><span class="cl">gcloud compute target-https-proxies update web-proxy --certificate-map<span class="o">=</span>web-map
</span></span></code></pre></td></tr></table>
</div>
</div><p>Once the certificate is <code>ACTIVE</code>, you flip the A/AAAA and the cutover is zero. CAA applies the same way.</p>
<h2 id="traps">Traps</h2>
<ul>
<li><strong>Cloudflare or another proxy in front</strong> of the load balancer: the A record points at the proxy, not at Google, and validation fails with <code>FAILED_NOT_VISIBLE</code>. Grey cloud during issuance, or Certificate Manager with DNS authorization.</li>
<li><strong>A managed certificate attached to nothing never gets issued.</strong> Creating it and waiting does nothing; attach it to the target proxy first.</li>
<li><strong>Changing the domain list</strong> creates a new certificate: attach the new one, wait for <code>ACTIVE</code>, and only then remove the old one from the proxy, or you get a gap.</li>
<li><strong>Wildcards</strong> only with Certificate Manager and DNS authorization; classic managed certificates do not support them.</li>
<li><strong>Badly signed DNSSEC</strong> breaks CAA lookups: <code>FAILED_CAA_CHECKING</code> even when you have no CAA at all.</li>
</ul>
<p>Reference: <a href="https://docs.cloud.google.com/load-balancing/docs/ssl-certificates/google-managed-certs">Google-managed SSL certificates</a> and <a href="https://docs.cloud.google.com/certificate-manager/docs/overview">Certificate Manager</a> in the Google Cloud documentation.</p>
]]></content:encoded></item></channel></rss>