PageSourceSearch

https://www.networktechguy.com/step-ca-certificate-revocation/

html networktechguy.com collected 2026-10-08 04:07:52 UTC 46,274 bytes, 736 lines download raw bytes

1<!DOCTYPE html>
2<html class="theme-dark" lang="en">
3
4<head>
5    <meta charset="utf-8">
6    <meta name="viewport" content="width=device-width, initial-scale=1">
7    <title>step-ca Certificate Revocation</title>
8    <link rel="stylesheet" href="/assets/built/screen.css?v=fbe86d181e">
9
10    <link rel="canonical" href="https://www.networktechguy.com/step-ca-certificate-revocation/">
11    <meta name="referrer" content="no-referrer-when-downgrade">
12    
13    <meta property="og:site_name" content="NetworkTechGuy.com">
14    <meta property="og:type" content="article">
15    <meta property="og:title" content="step-ca Certificate Revocation">
16    <meta property="og:description" content="In previous posts we successfully deployed our own PKI with step-ca and even configured traefik to use ACME protocol to request certificates from our PKI server. Now we are going to add an additional feature to our PKI, which is active certificate revocation.
17
18Smallstep’s step-ca as CA with ACME">
19    <meta property="og:url" content="https://www.networktechguy.com/step-ca-certificate-revocation/">
20    <meta property="og:image" content="https://www.networktechguy.com/content/images/2024/09/smallstep-2.png">
21    <meta property="article:published_time" content="2024-09-29T22:57:39.000Z">
22    <meta property="article:modified_time" content="2024-09-29T22:57:39.000Z">
23    <meta property="article:tag" content="smallstep">
24    <meta property="article:tag" content="step">
25    <meta property="article:tag" content="step-ca">
26    <meta property="article:tag" content="pki">
27    
28    <meta property="article:publisher" content="https://www.facebook.com/ghost">
29    <meta name="twitter:card" content="summary_large_image">
30    <meta name="twitter:title" content="step-ca Certificate Revocation">
31    <meta name="twitter:description" content="In previous posts we successfully deployed our own PKI with step-ca and even configured traefik to use ACME protocol to request certificates from our PKI server. Now we are going to add an additional feature to our PKI, which is active certificate revocation.
32
33Smallstep’s step-ca as CA with ACME">
34    <meta name="twitter:url" content="https://www.networktechguy.com/step-ca-certificate-revocation/">
35    <meta name="twitter:image" content="https://www.networktechguy.com/content/images/2024/09/smallstep-2.png">
36    <meta name="twitter:label1" content="Written by">
37    <meta name="twitter:data1" content="Nenad Karlovcec">
38    <meta name="twitter:label2" content="Filed under">
39    <meta name="twitter:data2" content="smallstep, step, step-ca, pki">
40    <meta name="twitter:site" content="@ghost">
41    <meta name="twitter:creator" content="@xnex">
42    <meta property="og:image:width" content="311">
43    <meta property="og:image:height" content="162">
44    
45    
45<script type="application/ld+json">
46{
47    "@context": "https://schema.org",
48    "@type": "Article",
49    "publisher": {
50        "@type": "Organization",
51        "name": "NetworkTechGuy.com",
52        "url": "https://www.networktechguy.com/",
53        "logo": {
54            "@type": "ImageObject",
55            "url": "https://www.networktechguy.com/favicon.ico",
56            "width": 48,
57            "height": 48
58        }
59    },
60    "author": {
61        "@type": "Person",
62        "name": "Nenad Karlovcec",
63        "image": {
64            "@type": "ImageObject",
65            "url": "https://www.networktechguy.com/content/images/2022/06/profilna.jpg",
66            "width": 960,
67            "height": 960
68        },
69        "url": "https://www.networktechguy.com/author/nex/",
70        "sameAs": [
71            "https://www.karlovcec.net",
72            "https://twitter.com/xnex"
73        ]
74    },
75    "headline": "step-ca Certificate Revocation",
76    "url": "https://www.networktechguy.com/step-ca-certificate-revocation/",
77    "datePublished": "2024-09-29T22:57:39.000Z",
78    "dateModified": "2024-09-29T22:57:39.000Z",
79    "image": {
80        "@type": "ImageObject",
81        "url": "https://www.networktechguy.com/content/images/2024/09/smallstep-2.png",
82        "width": 311,
83        "height": 162
84    },
85    "keywords": "smallstep, step, step-ca, pki",
86    "description": "In previous posts we successfully deployed our own PKI with step-ca and even configured traefik to use ACME protocol to request certificates from our PKI server. Now we are going to add an additional feature to our PKI, which is active certificate revocation.\n\nSmallstep’s step-ca as CA with ACME supportIn this blog post, we will go through the basic installation process and install both the step-ca and step-cli tool that will help us manage our CA and certificates issued by the CA.NetworkTechGuy",
87    "mainEntityOfPage": "https://www.networktechguy.com/step-ca-certificate-revocation/"
88}
89    </script>
89
90
91    <meta name="generator" content="Ghost 5.109">
92    <link rel="alternate" type="application/rss+xml" title="NetworkTechGuy.com" href="https://www.networktechguy.com/rss/">
93    
93<script defer src="https://cdn.jsdelivr.net/ghost/portal@~2.49/umd/portal.min.js" data-i18n="true" data-ghost="https://www.networktechguy.com/" data-key="53622933082ad9942fbcd6911f" data-api="https://www.networktechguy.com/ghost/api/content/" data-locale="en" crossorigin="anonymous"></script>
93<style id="gh-members-styles">.gh-post-upgrade-cta-content,
94.gh-post-upgrade-cta {
95    display: flex;
96    flex-direction: column;
97    align-items: center;
98    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
99    text-align: center;
100    width: 100%;
101    color: #ffffff;
102    font-size: 16px;
103}
104
105.gh-post-upgrade-cta-content {
106    border-radius: 8px;
107    padding: 40px 4vw;
108}
109
110.gh-post-upgrade-cta h2 {
111    color: #ffffff;
112    font-size: 28px;
113    letter-spacing: -0.2px;
114    margin: 0;
115    padding: 0;
116}
117
118.gh-post-upgrade-cta p {
119    margin: 20px 0 0;
120    padding: 0;
121}
122
123.gh-post-upgrade-cta small {
124    font-size: 16px;
125    letter-spacing: -0.2px;
126}
127
128.gh-post-upgrade-cta a {
129    color: #ffffff;
130    cursor: pointer;
131    font-weight: 500;
132    box-shadow: none;
133    text-decoration: underline;
134}
135
136.gh-post-upgrade-cta a:hover {
137    color: #ffffff;
138    opacity: 0.8;
139    box-shadow: none;
140    text-decoration: underline;
141}
142
143.gh-post-upgrade-cta a.gh-btn {
144    display: block;
145    background: #ffffff;
146    text-decoration: none;
147    margin: 28px 0 0;
148    padding: 8px 18px;
149    border-radius: 4px;
150    font-size: 16px;
151    font-weight: 600;
152}
153
154.gh-post-upgrade-cta a.gh-btn:hover {
155    opacity: 0.92;
156}</style>
157    
157<script defer src="https://cdn.jsdelivr.net/ghost/sodo-search@~1.5/umd/sodo-search.min.js" data-key="53622933082ad9942fbcd6911f" data-styles="https://cdn.jsdelivr.net/ghost/sodo-search@~1.5/umd/main.css" data-sodo-search="https://www.networktechguy.com/" data-locale="en" crossorigin="anonymous"></script>
157
158    
159    <link href="https://www.networktechguy.com/webmentions/receive/" rel="webmention">
160    
160<script defer src="/public/cards.min.js?v=fbe86d181e"></script>
160
161    <link rel="stylesheet" type="text/css" href="/public/cards.min.css?v=fbe86d181e">
162    
162<script defer src="/public/comment-counts.min.js?v=fbe86d181e" data-ghost-comments-counts-api="https://www.networktechguy.com/members/api/comments/counts/"></script>
162
163    
163<script defer src="/public/member-attribution.min.js?v=fbe86d181e"></script>
163<style>:root {--ghost-accent-color: #3daa9b;}</style>
164    <link
165  rel="stylesheet"
166  href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.0.2/styles/default.min.css"
167  integrity="sha256-48w2xk74a+0hWSZT2qyC/X5MNkwyyDRDNqoT99v1LJA="
168  crossorigin="anonymous"
169/>
170
171<style>
172    .u-object-fit {
173        object-fit: contain!important;
174        width: 100%;
175        height: auto;
176        max-height: 100%;
177        display: block;
178        margin: auto;
179        position: absolute;
180        top: 50%;
181        transform: translateY(-50%);
182    }
183
184    .single-media {
185        position: relative;
186    }
187</style>
188
189<style>
190.kg-card.kg-bookmark-card,
191.kg-card.kg-bookmark-card .kg-bookmark-container {
192    background-color: #282c35 !important;
193    color: #ffffff;
194    transition: background-color 0.3s, color 0.3s; /* Add transition for smoother effect */
195}
196
197.kg-card.kg-bookmark-card .kg-bookmark-title,
198.kg-card.kg-bookmark-card .kg-bookmark-description,
199.kg-card.kg-bookmark-card .kg-bookmark-metadata .kg-bookmark-author {
200    color: #ffffff; /* Set the initial color for title and description text */
201}
202
203.kg-card.kg-bookmark-card .kg-bookmark-container:hover {
204    background-color: #ffffff !important; /* Change background color on hover */
205    color: #000000 !important; /* Change text color on hover */
206}
207
208.kg-card.kg-bookmark-card .kg-bookmark-container:hover .kg-bookmark-title,
209.kg-card.kg-bookmark-card .kg-bookmark-container:hover .kg-bookmark-description,
210.kg-card.kg-bookmark-card .kg-bookmark-container:hover .kg-bookmark-metadata .kg-bookmark-author {
211    color: #000000 !important; /* Change text color on hover */
212}
213</style>
214<!-- Matomo -->
215<script>
216  var _paq = window._paq = window._paq || [];
217  /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
218  _paq.push(['trackPageView']);
219  _paq.push(['enableLinkTracking']);
220  (function() {
221    var u="//analytics.karlonet.com/";
222    _paq.push(['setTrackerUrl', u+'matomo.php']);
223    _paq.push(['setSiteId', '2']);
224    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
225    g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
226  })();
227</script>
227
228<!-- End Matomo Code -->
229</head>
230
231<body class='post-template tag-smallstep tag-step tag-step-ca tag-pki is-head-left-logo'>
232<div class="site">
233
234    <header id="gh-head" class="gh-head gh-outer">
235        <div class="gh-head-inner gh-inner">
236            <div class="gh-head-brand">
237                <div class="gh-head-brand-wrapper">
238                    <a class="gh-head-logo" href="https://www.networktechguy.com">
239                            NetworkTechGuy.com
240                    </a>
241                </div>
242                <button class="gh-search gh-icon-btn" aria-label="Search this site" data-ghost-search><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" width="20" height="20"><path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg></button>
243                <button class="gh-burger"></button>
244            </div>
245
246            <nav class="gh-head-menu">
247                <ul class="nav">
248    <li class="nav-home"><a href="https://www.networktechguy.com/">Home</a></li>
249    <li class="nav-about"><a href="https://www.networktechguy.com/about/">About</a></li>
250</ul>
251
252            </nav>
253
254            <div class="gh-head-actions">
255                    <button class="gh-search gh-icon-btn" aria-label="Search this site" data-ghost-search><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" width="20" height="20"><path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg></button>
256                    <div class="gh-head-members">
257                                <a class="gh-head-link" href="#/portal/signin" data-portal="signin">Sign in</a>
258                                <a class="gh-head-btn gh-btn gh-primary-btn" href="#/portal/signup" data-portal="signup">Subscribe</a>
259                    </div>
260            </div>
261        </div>
262    </header>
263
264
265    <div class="site-content">
266        
267<main class="site-main">
268
269        <article class="single post tag-smallstep tag-step tag-step-ca tag-pki featured">
270
271        <header class="single-header gh-canvas">
272            <div class="single-meta">
273                <span class="single-meta-item single-meta-date">
274                    <time datetime="2024-09-29">
275                        Sep 29, 2024
276                    </time>
277                </span>
278                    <span class="single-meta-item single-meta-length">
279                        10 min read
280                    </span>
281                    <span class="single-meta-item single-meta-tag">
282                        <a class="post-tag post-tag-smallstep" href="/tag/smallstep/">
283                            smallstep
284                        </a>
285                    </span>
286            </div>
287
288            <h1 class="single-title">step-ca Certificate Revocation</h1>
289
290
291        </header>
292
293    <div class="single-content gh-content gh-canvas">
294        <p>In previous posts we successfully deployed our own PKI with <code>step-ca</code> and even configured <code>traefik</code> to use ACME protocol to request certificates from our PKI server. Now we are going to add an additional feature to our PKI, which is active certificate revocation. </p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.networktechguy.com/smallsteps-step-ca-as-ca-with-acme-support/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Smallstep’s step-ca as CA with ACME support</div><div class="kg-bookmark-description">In this blog post, we will go through the basic installation process and install both the step-ca and step-cli tool that will help us manage our CA and certificates issued by the CA.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://www.networktechguy.com/favicon.ico" alt=""><span class="kg-bookmark-author">NetworkTechGuy.com</span><span class="kg-bookmark-publisher">Nenad Karlovcec</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://www.networktechguy.com/content/images/2024/09/smallstep-1.png" alt=""></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.networktechguy.com/using-traefik-with-local-ca-with-acme-support/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Using traefik with local CA with ACME support</div><div class="kg-bookmark-description">How to use custom PKI through ACME calls with traefik.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://www.networktechguy.com/favicon.ico" alt=""><span class="kg-bookmark-author">NetworkTechGuy.com</span><span class="kg-bookmark-publisher">Nenad Karlovcec</span></div></div>
294<div class="kg-bookmark-thumbnail"><img src="https://www.networktechguy.com/content/images/2024/09/logo-traefik-proxy-logo.svg" alt=""></div></a></figure><p>Please keep in mind that active revocation via CRLs (Certificate Revocation Lists) is not a perfect solution to certificate revocation - ideally, you would be issuing short-lived certificates that you will just let expire. Another issue is that it heavily relies on browsers to do the work, and since they use different methods to check validity of a certificate, results may vary. Once expired, certificate can no longer be used for authentication. Additionally, you can set the certificate to be revoked via <code>step-ca</code> and, once revoked, it cannot be renewed. </p><p>For that reason, <a href="https://smallstep.com/?ref=networktechguy.com" rel="noreferrer"><em>Smallstep</em></a> actually recommends passive revocation through short-lived certificates. However, sometimes your services will require certificates that have CRLs included in them - one recent example for me was when I tried installing a new certificate for a test Exchange server. There was simply no way to get it to work (or I couldn't figure out how to do it) without having the extra extension in the certificate (<em>X509v3 CRL Distribution Points</em>). And so I went researching on how to get the CRL working with my <code>step-ca</code> installation. Luckily, with the version of <code>step-ca</code> I'm running, you are able to enable a minimal <em>Certificate Revocation List</em> server. I don't know if this is a new thing or something, as on some other parts of their documentation, they specifically state that they don't support active revocation, but I'm not going to complain about that 😄.</p><p>So let's take a look at what needs to be done. There are actually a few steps:</p><ul><li>modify your existing <code>step-ca</code> server's <code>ca.json</code> file to enable insecure port and URL for the CRL</li><li>create a new template for your <em>intermediate</em> <em>CA</em> that is used for signing all your certificates; once that is completed, you will generate a new <em>intermediate CA</em> and its accompanying key</li><li>you will also want to create a <em>leaf</em> template for all your new certificates to include the <em>CRL</em> as well</li><li>finally, you will want to modify your <code>ca.json</code> file again to include the new leaf template when issuing certificates</li></ul><h2 id="modify-ca-server-configuration">Modify CA server configuration</h2><p>Let's start with modifying our <em>CA</em> server configuration. There's a few things that need to be added at the start:</p><pre><code class="language-bash">        "insecureAddress": ":80",
295        "crl": {
296                "enabled": true,
297                "cacheDuration": "8h0m0s",
298                "idpURL": "http://ca.demo.networktechguy.com/1.0/crl"
299        },</code></pre><p>Looking from the beginning of the file, it should be fit something like this:</p><pre><code class="language-bash">$ cat config/ca.json 
300
301{
302        "root": "/etc/step-ca/certs/root_ca.crt",
303        "federatedRoots": null,
304        "crt": "/etc/step-ca/certs/intermediate_ca.crt",
305        "key": "/etc/step-ca/secrets/intermediate_ca_key",
306        "address": ":443",
307        "insecureAddress": ":80",
308        "commonName": "NetworkTechGuy.com Demo CA",
309        "crl": {
310                "enabled": true,
311                "cacheDuration": "8h0m0s",
312                "idpURL": "http://ca.demo.networktechguy.com/1.0/crl"
313        },
314        "dnsNames": [
315                "ca.demo.networktechguy.com",
316                "10.75.1.10"
317        ],
318
319---OUTPUT OMITTED---</code></pre><p>At this point I would restart the service as it is easier to troubleshoot potential problems while we are just beginning with the process:</p><pre><code class="language-bash">sudo systemctl restart step-ca
320sudo systemctl status step-ca
321</code></pre><p>If you get something like this for status:</p><pre><code class="language-bash">     Active: active (running) since Sun 2024-09-29 14:39:29 EDT; 1s ago</code></pre><p>It means that the service has been successfully restarted. If not, check the logs with <code>journalctl</code>:</p><pre><code class="language-bash">
321sudo journalctl -u step-ca</code></pre><h2 id="create-new-intermediate-ca-template-file">Create new intermediate CA template file</h2><p>New template file will be <code>intermediate.tpl</code> and we can place it in the <code>/etc/step-ca/templates</code> directory. Content should be something like this:</p><pre><code class="language-json">{
322    "subject": {{ toJson .Subject }},
323    "keyUsage": ["certSign", "crlSign"],
324    "basicConstraints": {
325        "isCA": true,
326        "maxPathLen": 0
327    },
328    "crlDistributionPoints": ["http://ca.demo.networktechguy.com/1.0/crl"]
329}</code></pre><p>We can now generate new <em>intermediate CA</em>:</p><pre><code class="language-bash">step certificate create \
330     --template /etc/step-ca/templates/intermediate.tpl \
331     --ca $(step path)/certs/root_ca.crt \
332     --ca-key $(step path)/secrets/root_ca_key \
333     --not-after 87660h \
334     "NetworkTechGuy.com CA Intermediate CA" \
335     $(step path)/certs/intermediate_ca.crt \
336     $(step path)/secrets/intermediate_ca_key</code></pre><p>Please note that, for this command to work, you need to have completed the setup of the server as explained <a href="https://www.networktechguy.com/smallsteps-step-ca-as-ca-with-acme-support/" rel="noreferrer">here</a>, otherwise use full path (<code>/etc/step-ca/</code>) instead of variables (<code>$(step path)/</code>).</p><p>The whole process should look something like this:</p><pre><code class="language-bash">$ sudo step certificate create \
337--template /etc/step-ca/templates/intermediate.tpl \
338--ca $(step path)/certs/root_ca.crt \
339--ca-key $(step path)/secrets/root_ca_key \
340--not-after 87660h \
341"NetworkTechGuy.com CA Intermediate CA"  \
342$(step path)/certs/intermediate_ca.crt \
343$(step path)/secrets/intermediate_ca_key
344
345Please enter the password to decrypt /etc/step-ca/secrets/root_ca_key: ��������
346Please enter the password to encrypt the private key: ��������
347✔ Would you like to overwrite /etc/step-ca/secrets/intermediate_ca_key [y/n]: y
348✔ Would you like to overwrite /etc/step-ca/certs/intermediate_ca.crt [y/n]: y
349Your certificate has been saved in /etc/step-ca/certs/intermediate_ca.crt.
350Your private key has been saved in /etc/step-ca/secrets/intermediate_ca_key.</code></pre><p>As you can see, you will be asked to overwrite the existing <em>intermediate</em> cert and key. Since all of your certificates are authenticated against the <code>root</code> CA, and we are not changing that, feel free to do so.</p><p>If we inspect the newly created certificate, we can see that it now includes the needed extension:</p><pre><code class="language-bash">$ step certificate inspect /etc/step-ca/certs/intermediate_ca.crt 
351
352Certificate:
353---OUTPUT OMITTED---
354            X509v3 CRL Distribution Points:
355                Full Name:
356                  URI:http://ca.demo.networktechguy.com/1.0/crl
357---OUTPUT OMITTED---</code></pre><p>Next, we will restart the service and check the status:</p><pre><code class="language-bash">$ sudo systemctl restart step-ca
358$ sudo systemctl status step-ca
359
360● step-ca.service - step-ca service
361     Loaded: loaded (/etc/systemd/system/step-ca.service; enabled; preset: enabled)
362     Active: active (running) since Sun 2024-09-29 14:36:05 EDT; 16s ago
363       Docs: https://smallstep.com/docs/step-ca
364             https://smallstep.com/docs/step-ca/certificate-authority-server-production
365   Main PID: 3086 (step-ca)
366      Tasks: 9 (limit: 4643)
367     Memory: 17.3M
368        CPU: 156ms
369     CGroup: /system.slice/step-ca.service
370             └─3086 /usr/bin/step-ca config/ca.json --password-file password.txt
371
372Sep 29 14:36:05 deb-step-01 systemd[1]: Started step-ca.service - step-ca service.</code></pre><h2 id="creating-a-leaf-template">Creating a leaf template</h2><p>Next, let's create a <em>leaf</em> template. The content should look something like this:</p><pre><code class="language-json">{
373  "subject": {{ toJson .Subject }},
374  "sans": {{ toJson .SANs }},
375  {{- if typeIs "*rsa.PublicKey" .Insecure.CR.PublicKey }}
376  "keyUsage": ["keyEncipherment", "digitalSignature"],
377  {{- else }}
378  "keyUsage": ["digitalSignature"],
379  {{- end }}
380  "extKeyUsage": ["serverAuth", "clientAuth"],
381  "crlDistributionPoints": ["http://ca.demo.networktechguy.com/1.0/crl"]
382}</code></pre><p>I've placed in a newly created <em>subdirectory</em> (<code>x509</code>) of the <em>templates</em> <em>directory</em>, so the full path of the file is <code>/etc/step-ca/templates/x509/leaf.tpl</code>. </p><h2 id="modify-provisioners-to-use-new-template-file">Modify provisioners to use new template file</h2><p>There are two ways to do it - one way is to do it via <code>step ca provisioner</code> command, like this:</p><pre><code class="language-bash">step ca provisioner update NTG --x509-template /etc/step-ca/templates/x509/leaf.tpl</code></pre><p>Please keep in mind that if you want <em>ACME</em> certificates to use the new template file, you have to do it for that <em>provisioner</em> as well:</p><pre><code class="language-bash">step ca provisioner update acme --x509-template /etc/step-ca/templates/x509/leaf.tpl</code></pre><p>Now, with that said, this will modify your <code>ca.json</code> file and add whatever was in the <code>leaf.tpl</code> file into the <code>ca.json</code> file, in-line:</p><pre><code class="language-json">                        {
383                                "type": "JWK",
384                                "name": "NTG",
385                                "key": {
386                                        "use": "sig",
387                                        "kty": "EC",
388                                        "kid": "---OUTPUT OMITTED---",
389                                        "crv": "P-256",
390                                        "alg": "ES256",
391                                        "x": "---OUTPUT OMITTED---",
392                                        "y": "---OUTPUT OMITTED---"
393                                },
394                                "encryptedKey": "---OUTPUT OMITTED---",
395                                "claims": {
396                                        "minTLSCertDuration": "5m0s",
397                                        "maxTLSCertDuration": "43830h0m0s",
398                                        "defaultTLSCertDuration": "17532h0m0s",
399                                        "enableSSHCA": true,
400                                        "disableRenewal": false,
401                                        "allowRenewalAfterExpiry": false,
402                                        "disableSmallstepExtensions": false
403                                },
404                                "options": {
405                                        "x509": {
406                                                "template": "{\n  \"subject\": {{ toJson .Subject }},\n  \"sans\": {{ toJson .SANs }},\n  {{- if typeIs \"*rsa.PublicKey\" .Insecure.CR.PublicKey }}
406\n  \"keyUsage\": [\"keyEncipherment\", \"digitalSignature\"],\n  {{- else }}\n  \"keyUsage\": [\"digitalSignature\"],\n  {{- end }}\n  \"extKeyUsage\": [\"serverAuth\", \"clientAuth\"],\n  \"crlDistributionPoints\": [\"http://ca.demo.networktechguy.com/1.0/crl\"]\n}\n"
407                                        },
408                                        "ssh": {}
409                                }
410                        }</code></pre><p>I don't like that, so after I did it via these commands, I modified the file to look like this instead:</p><pre><code class="language-json">                        {
411                                "type": "JWK",
412                                "name": "NTG",
413                                "key": {
414                                        "use": "sig",
415                                        "kty": "EC",
416                                        "kid": "---OUTPUT OMITTED---",
417                                        "crv": "P-256",
418                                        "alg": "ES256",
419                                        "x": "---OUTPUT OMITTED---",
420                                        "y": "---OUTPUT OMITTED---"
421                                },
422                                "encryptedKey": "---OUTPUT OMITTED---",
423                                "claims": {
424                                        "minTLSCertDuration": "5m0s",
425                                        "maxTLSCertDuration": "43830h0m0s",
426                                        "defaultTLSCertDuration": "17532h0m0s",
427                                        "enableSSHCA": true,
428                                        "disableRenewal": false,
429                                        "allowRenewalAfterExpiry": false,
430                                        "disableSmallstepExtensions": false
431                                },
432                                "options": {
433                                        "x509": {
434                                                "templateFile": "/etc/step-ca/templates/x509/leaf.tpl"
435                                        },
436                                        "ssh": {}
437                                }
438                        },</code></pre><p>This is an output for <em>JWK</em> <em>provisioner</em> only, if you added the new <em>leaf</em> template to <em>ACME</em> <em>provisioner</em>, you will have to fix it there as well.</p><p>For this to work, make sure that your template file has correct ownership and permissions:</p><pre><code class="language-bash">$ ls -alh /etc/step-ca/templates/x509/leaf.tpl
439
440-rw-r--r-- 1 step step 367 Sep 29 13:39 templates/x509/leaf.tpl</code></pre><p>Finally, restart the service and check the status:</p><pre><code class="language-bash">sudo systemctl restart step-ca
441sudo systemctl status step-ca</code></pre><p>If everything is working after all these changes, you can check the status of your <em>CRL</em> server - I'm doing this now on the workstation, as all the changes on the server are complete:</p><pre><code class="language-bash">$ step crl inspect http://ca.demo.networktechguy.com/1.0/crl --insecure</code></pre><p>Results should be something like this:</p><pre><code class="language-bash">$ step crl inspect http://ca.demo.networktechguy.com/1.0/crl --insecure
442
443Certificate Revocation List (CRL):
444    Data:
445        Valid: false
446        Version: 17 (0x11)
447    Signature algorithm: ECDSA-SHA256
448        Issuer: 
449        Last Update: 2024-09-29 20:57:38 +0000 UTC
450        Next Update: 2024-09-30 04:57:38 +0000 UTC
451        CRL Extensions:
452            X509v3 Authority Key Identifier:
453                keyid:1B:20:FA:72:A8:A4:26:10:D9:B2:8D:AC:29:88:DB:13:B9:1D:7E:7F
454            X509v3 CRL Number:
455                17
456            X509v3 Issuing Distribution Point: critical
457                Full Name:
458                    URI:http://ca.demo.networktechguy.com/1.0/crl
459                Only User Certificates
460        Revoked Certificates:
461            Serial Number: 14901852086807387906094692013751768567 (0x0B35FE086D3BF2E8D33BB60BED8595F7)
462                Revocation Date: 2024-09-29 19:59:04 +0000 UTC
463            Serial Number: 165745321111098419965161888279534387093 (0x7CB16340C3FCA91B5F07181E28C63F95)
464                Revocation Date: 2024-09-29 19:45:44 +0000 UTC
465            Serial Number: 265544075792166084197075778072633340760 (0xC7C5EDC016778C94A2B743E32F86F358)
466                Revocation Date: 2024-09-29 18:56:15 +0000 UTC
467            Serial Number: 287599246715617662997638596379242195474 (0xD85D99A1ADEDF37E0FDDB0A31EC8EA12)
468                Revocation Date: 2024-09-29 19:32:29 +0000 UTC
469    Signature Algorithm: ECDSA-SHA256
470        30:45:02:20:0b:c8:a8:4a:8a:0e:08:5d:83:cb:54:d9:
471        15:7a:c7:4d:24:17:f6:62:18:36:5b:d7:55:e0:b8:75:
472        83:8f:3e:e1:02:21:00:99:7c:06:0d:95:7b:2f:ba:d2:
473        31:63:71:b1:88:75:89:67:a1:24:ed:4e:5a:e3:6c:b1:
474        d7:a0:3c:d2:b3:b4:66</code></pre><p>You will notice that I already have a few revoked certificates in my list. Also, notice that updates are done in 8-hour intervals, as configured here:</p><pre><code class="language-bash">                "cacheDuration": "8h0m0s",</code></pre><p>If you don't want to wait this long, you can always change the value to something that fits your needs better. Also, when you issue a <em>service restart</em> command, it will also clear the <em>cache</em>.</p><p>So let's try and create a new certificate with this new setup. One thing to note is that I changed the minimum <em>TLS</em> certificate duration parameter from the time I posted previous article, so it is now set to 5 minutes:</p><pre><code class="language-json">                                        "minTLSCertDuration": "5m0s",</code></pre><p>New certificate request:</p><pre><code class="language-bash">$ step ca certificate test-06.demo.networktechguy.com test-06.demo.networktechguy.com.crt test-06.demo.networktechguy.com.key --not-after=60m
475
476✔ Provisioner: NTG (JWK) [kid: 6zkvMKLGZxf0qa4n-cleOyn2seI04fweoAuOjBlcr4A]
477Please enter the password to decrypt the provisioner key: ��������
478✔ CA: https://ca.demo.networktechguy.com
479✔ Certificate: test-06.demo.networktechguy.com.crt
480✔ Private Key: test-06.demo.networktechguy.com.key</code></pre><p>Let's inspect the new certificate:</p><pre><code class="language-bash">step certificate inspect test-06.demo.networktechguy.com.crt 
481Certificate:
482---OUTPUT OMITTED---
483        Issuer: CN=NetworkTechGuy.com CA Intermediate CA
484        Validity
485            Not Before: Sep 29 21:40:32 2024 UTC
486            Not After : Sep 29 22:41:32 2024 UTC
487        Subject: CN=test-06.demo.networktechguy.com
488---OUTPUT OMITTED---
489            X509v3 Subject Alternative Name:
490                DNS:test-06.demo.networktechguy.com
491            X509v3 CRL Distribution Points:
492                Full Name:
493                  URI:http://ca.demo.networktechguy.com/1.0/crl
494---OUTPUT OMITTED---</code></pre><p>What we can see from the output is that the new certificate has a one hour validity and that the <em>CRL</em> distribution point is included in the extensions. From this point on, any service that requires <em>CRL</em> extension to be included in the certificate, should be happy!</p><p>As for the revocation, it's quite easy to do. When you inspect the certificate, you will notice that there is a serial number of the certificate at the beginning:</p><pre><code class="language-bash">$ step certificate inspect test-06.demo.networktechguy.com.crt 
495
496Certificate:
497    Data:
498        Version: 3 (0x2)
499        Serial Number: 65623237680889282882253127865884846522 (0x315e936ae33eec9d05dca6a17c99a9ba)</code></pre><p>We will use this serial number to revoke the certificate:</p><pre><code class="language-bash">$ step ca revoke 65623237680889282882253127865884846522 --reason="No longer needed"
500
501✔ Provisioner: NTG (JWK) [kid: 6zkvMKLGZxf0qa4n-cleOyn2seI04fweoAuOjBlcr4A]
502Please enter the password to decrypt the provisioner key: ��������
503✔ CA: https://ca.demo.networktechguy.com
504Certificate with Serial Number 65623237680889282882253127865884846522 has been revoked.</code></pre><p>If we were to check the status of the <em>CRL</em> right now, it would not reflect the change as it's reading the list from the cache:</p><pre><code class="language-bash">$ step crl inspect http://ca.demo.networktechguy.com/1.0/crl --insecure
505---OUTPUT OMITTED---
506        Revoked Certificates:
507            Serial Number: 14901852086807387906094692013751768567 (0x0B35FE086D3BF2E8D33BB60BED8595F7)
508                Revocation Date: 2024-09-29 19:59:04 +0000 UTC
509            Serial Number: 165745321111098419965161888279534387093 (0x7CB16340C3FCA91B5F07181E28C63F95)
510                Revocation Date: 2024-09-29 19:45:44 +0000 UTC
511            Serial Number: 265544075792166084197075778072633340760 (0xC7C5EDC016778C94A2B743E32F86F358)
512                Revocation Date: 2024-09-29 18:56:15 +0000 UTC
513            Serial Number: 287599246715617662997638596379242195474 (0xD85D99A1ADEDF37E0FDDB0A31EC8EA12)
514                Revocation Date: 2024-09-29 19:32:29 +0000 UTC</code></pre><p>As you can see, our certificate is not on the list of revoked certificates (yet). To manually refresh the <em>CRL</em>, restart the service on the server and then try again:</p><pre><code class="language-bash">step crl inspect http://ca.demo.networktechguy.com/1.0/crl --insecure
515---OUTPUT OMITTED---
516            Serial Number: 65623237680889282882253127865884846522 (0x315E936AE33EEC9D05DCA6A17C99A9BA)
517                Revocation Date: 2024-09-29 21:50:41 +0000 UTC
518---OUTPUT OMITTED---</code></pre><p>As you can see, this certificate is now successfully revoked and any service that utilises CRLs will see that it's been revoked.</p><h2 id="conclusion">Conclusion</h2><p>Unfortunately, status of browser <em>CRL</em> checks is not that great at the moment. Even though certificate has been revoked, and it is so stated in the inspection, I have yet to figure out how to get my browsers to actually check the <em>CRL</em> stated in the certificate itself. That's why consider this blog post a half-done - if a <strong>service</strong> requires a <em>CRL</em> extension to be present in the certificate - this will do. If <strong>you</strong> require <em>CRL</em> checks to be performed against issued certificates, this does not (yet) work. I will continue looking into this to see how (and <strong>if</strong>) I can make it work, but for now, consider passive revocation - issue personal certificates with validity that you are comfortable with. If you want someone to temporarily access your service, issue them a certificate with validity of one day for example and that will work without an issue. Hopefully there's a solution for this that I'm just not aware of.</p>
519    </div>
520
521    <div class="gh-canvas">
522    <footer class="single-footer">
523
524        <div class="single-footer-left">
525            <div class="navigation navigation-previous">
526                <a class="navigation-link" href="/traefik-with-mtls/" aria-label="Previous post">
527                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="currentColor" class="icon navigation-icon">
528    <path d="M26.667 14.667v2.667h-16L18 24.667l-1.893 1.893L5.547 16l10.56-10.56L18 7.333l-7.333 7.333h16z"></path>
529</svg>                </a>
530            </div>
531        </div>
532
533        <div class="single-footer-middle">
534            <div class="single-footer-top">
535                <h3 class="single-footer-title">Published by:</h3>
536                <div class="author-list">
537                    <div class="author-image-placeholder u-placeholder square">
538                        <a href="/author/nex/" title="Nenad Karlovcec">
539                            <img class="author-image u-object-fit" src="/content/images/size/w150/2022/06/profilna.jpg" alt="Nenad Karlovcec" loading="lazy">
540                        </a>
541                    </div>
542                </div>
543            </div>
544        </div>
545
546        <div class="single-footer-right">
547            <div class="navigation navigation-next">
548                <a class="navigation-link" href="/proxmox-changing-windows-10-bios-from-seabios-to-ovmf-uefi/" aria-label="Next post">
549                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="currentColor" class="icon navigation-icon">
550    <path d="M5.333 14.667v2.667h16L14 24.667l1.893 1.893L26.453 16 15.893 5.44 14 7.333l7.333 7.333h-16z"></path>
551</svg>                </a>
552            </div>
553        </div>
554
555    </footer>
556    </div>
557
558</article>
559                <section class="related-wrapper gh-canvas">
560        <h3 class="related-title">You might also like...</h3>
561        <div class="related-feed">
562                <article class="feed public post featured">
563
564    <div class="feed-calendar">
565        <div class="feed-calendar-month">
566            Sep
567        </div>
568        <div class="feed-calendar-day">
569            28
570        </div>
571    </div>
572
573    <h2 class="feed-title">Traefik with mTLS</h2>
574
575    <div class="feed-right">
576        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="currentColor" class="icon icon-star">
577    <path d="M16 23.027L24.24 28l-2.187-9.373 7.28-6.307-9.587-.827-3.747-8.827-3.747 8.827-9.587.827 7.267 6.307L7.759 28l8.24-4.973z"></path>
578</svg>        <div class="feed-length">
579            11 min read
580        </div>
581    </div>
582
583    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="currentColor" class="icon feed-icon">
584    <path d="M11.453 22.107L17.56 16l-6.107-6.12L13.333 8l8 8-8 8-1.88-1.893z"></path>
585</svg>
586    <a class="u-permalink" href="/traefik-with-mtls/" aria-label="Traefik with mTLS"></a>
587
588</article>                <article class="feed public post featured">
589
590    <div class="feed-calendar">
591        <div class="feed-calendar-month">
592            Sep
593        </div>
594        <div class="feed-calendar-day">
595            28
596        </div>
597    </div>
598
599    <h2 class="feed-title">Using traefik with local CA with ACME support</h2>
600
601    <div class="feed-right">
602        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="currentColor" class="icon icon-star">
603    <path d="M16 23.027L24.24 28l-2.187-9.373 7.28-6.307-9.587-.827-3.747-8.827-3.747 8.827-9.587.827 7.267 6.307L7.759 28l8.24-4.973z"></path>
604</svg>        <div class="feed-length">
605            10 min read
606        </div>
607    </div>
608
609    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="currentColor" class="icon feed-icon">
610    <path d="M11.453 22.107L17.56 16l-6.107-6.12L13.333 8l8 8-8 8-1.88-1.893z"></path>
611</svg>
612    <a class="u-permalink" href="/using-traefik-with-local-ca-with-acme-support/" aria-label="Using traefik with local CA with ACME support"></a>
613
614</article>                <article class="feed public post featured">
615
616    <div class="feed-calendar">
617        <div class="feed-calendar-month">
618            Sep
619        </div>
620        <div class="feed-calendar-day">
621            28
622        </div>
623    </div>
624
625    <h2 class="feed-title">Smallstep&#x27;s step-ca as CA with ACME support</h2>
626
627    <div class="feed-right">
628        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="currentColor" class="icon icon-star">
629    <path d="M16 23.027L24.24 28l-2.187-9.373 7.28-6.307-9.587-.827-3.747-8.827-3.747 8.827-9.587.827 7.267 6.307L7.759 28l8.24-4.973z"></path>
630</svg>        <div class="feed-length">
631            29 min read
632        </div>
633    </div>
634
635    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="currentColor" class="icon feed-icon">
636    <path d="M11.453 22.107L17.56 16l-6.107-6.12L13.333 8l8 8-8 8-1.88-1.893z"></path>
637</svg>
638    <a class="u-permalink" href="/smallsteps-step-ca-as-ca-with-acme-support/" aria-label="Smallstep&#x27;s step-ca as CA with ACME support"></a>
639
640</article>        </div>
641    </section>
642
643                <section class="gh-comments gh-canvas">
644        <header class="gh-comments-header">
645            <h3 class="gh-comments-title related-title">Member discussion</h3>
646            
646<script
647    data-ghost-comment-count="66f9b308104ad400011e7442"
648    data-ghost-comment-count-empty=""
649    data-ghost-comment-count-singular="comment"
650    data-ghost-comment-count-plural="comments"
651    data-ghost-comment-count-tag="span"
652    data-ghost-comment-count-class-name="gh-comments-count"
653    data-ghost-comment-count-autowrap="true"
654>
655</script>
655
656        </header>
657        
658        
658<script defer src="https://cdn.jsdelivr.net/ghost/comments-ui@~1.0/umd/comments-ui.min.js" data-locale="en" data-ghost-comments="https://www.networktechguy.com/" data-api="https://www.networktechguy.com/ghost/api/content/" data-admin="https://www.networktechguy.com/ghost/" data-key="53622933082ad9942fbcd6911f" data-title="" data-count="false" data-post-id="66f9b308104ad400011e7442" data-color-scheme="auto" data-avatar-saturation="60" data-accent-color="#3daa9b" data-comments-enabled="all" data-publication="NetworkTechGuy.com" crossorigin="anonymous"></script>
658
659    
660    </section>
661
662</main>
663    </div>
664
665    <footer class="gh-foot gh-outer">
666        <div class="gh-foot-inner gh-inner">
667            <div class="gh-copyright">
668                NetworkTechGuy.com © 2026
669            </div>
670                <nav class="gh-foot-menu">
671                    <ul class="nav">
672    <li class="nav-sign-up"><a href="#/portal/">Sign up</a></li>
673</ul>
674
675                </nav>
676            <div class="gh-powered-by">
677                <a href="https://ghost.org/" target="_blank" rel="noopener">Powered by Ghost</a>
678            </div>
679        </div>
680    </footer>
681
682</div>
683
684    <div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
685    <div class="pswp__bg"></div>
686
687    <div class="pswp__scroll-wrap">
688        <div class="pswp__container">
689            <div class="pswp__item"></div>
690            <div class="pswp__item"></div>
691            <div class="pswp__item"></div>
692        </div>
693
694        <div class="pswp__ui pswp__ui--hidden">
695            <div class="pswp__top-bar">
696                <div class="pswp__counter"></div>
697
698                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
699                <button class="pswp__button pswp__button--share" title="Share"></button>
700                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
701                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
702
703                <div class="pswp__preloader">
704                    <div class="pswp__preloader__icn">
705                        <div class="pswp__preloader__cut">
706                            <div class="pswp__preloader__donut"></div>
707                        </div>
708                    </div>
709                </div>
710            </div>
711
712            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
713                <div class="pswp__share-tooltip"></div>
714            </div>
715
716            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"></button>
717            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"></button>
718
719            <div class="pswp__caption">
720                <div class="pswp__caption__center"></div>
721            </div>
722        </div>
723    </div>
724</div>
725<script
726    src="https://code.jquery.com/jquery-3.5.1.min.js"
727    integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
728    crossorigin="anonymous">
729</script>
vendor: 1 bytes, line 729
729
730<script src='/assets/built/main.min.js?v=fbe86d181e'></script>
730
731
732
733
734<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v4bc70e2c01a94c73b74392e4234840661791215815920" integrity="sha512-L0ha0OXavK/8okipN9F8BtP84dg9DUhPERbBXzwI6dgTA55d2+yweo3pn5CSFYs45/r8md2+xvUPtTdvTNRfjA==" data-cf-beacon='{"version":"2024.11.0","token":"58e5ad7d6f7d4cc494aec957319e6801","r":1,"spa":2}' crossorigin="anonymous"></script>
vendor: 1 bytes, line 734
734
735<script>(function(){function c(){var b=a.contentDocument||(a.contentWindow&&a.contentWindow.document);if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'a47247f8e9f3e178',t:'MTc5MTQzMjQ3Mg=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script>
735</body>
736</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.