<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Erik Huelsmann</title>
    <description>The latest articles on DEV Community by Erik Huelsmann (@ehuelsmann).</description>
    <link>https://dev.to/ehuelsmann</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F573101%2F8957c5a0-b588-4b03-be4f-2e28e7f2c3cc.jpeg</url>
      <title>DEV Community: Erik Huelsmann</title>
      <link>https://dev.to/ehuelsmann</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ehuelsmann"/>
    <language>en</language>
    <item>
      <title>SSH with gpg-agent on systemd</title>
      <dc:creator>Erik Huelsmann</dc:creator>
      <pubDate>Fri, 12 Jul 2024 19:43:05 +0000</pubDate>
      <link>https://dev.to/ehuelsmann/ssh-with-gpg-agent-on-systemd-5ddf</link>
      <guid>https://dev.to/ehuelsmann/ssh-with-gpg-agent-on-systemd-5ddf</guid>
      <description>&lt;p&gt;There's a lot of information floating around on the web explaining how to replace &lt;code&gt;ssh-agent&lt;/code&gt; with &lt;code&gt;gpg-agent&lt;/code&gt;. This is important if you - like me - want to use a &lt;a href="https://www.yubico.com/" rel="noopener noreferrer"&gt;yubikey&lt;/a&gt; or smart card device to store the private key of your SSH key pair.&lt;/p&gt;

&lt;p&gt;Unfortunately, none of the advice worked for me with the following system setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;systemd v249&lt;/li&gt;
&lt;li&gt;GNOME desktop 42.9&lt;/li&gt;
&lt;li&gt;Ubuntu 22.04&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although the above is quite specific, I expect the information below to be much more generally applicable. [[edit: this article also applies to Ubuntu 24.04; I learned that after upgrading]]&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite for Yubikeys and smart cards
&lt;/h2&gt;

&lt;p&gt;GPG needs &lt;code&gt;pcscd&lt;/code&gt; and &lt;code&gt;scdaemon&lt;/code&gt; to be able to access private keys stored on a yubikey or smart card:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;pcscd scdaemon
&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; pcscd
&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; scdaemon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running these commands, &lt;code&gt;gpg --card-status&lt;/code&gt; should provide you with information about your smart card.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring GPG with ssh-agent support
&lt;/h2&gt;

&lt;p&gt;To enable ssh-agent support in gpg-agent, add the following to your gpg-agent.conf:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ~/.gnupg/gpg-agent.conf
enable-ssh-support
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Enabling &lt;code&gt;gpg-agent&lt;/code&gt; (per user)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;gpg-agent&lt;/code&gt; is a per-user service, which systemd facilitates with the &lt;code&gt;--user&lt;/code&gt; flag on the &lt;code&gt;systemctl&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; gpg-agent.socket
&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; gpg-agent-ssh.socket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you forget to add the &lt;code&gt;.socket&lt;/code&gt; extension, systemctl will throw an error about a missing &lt;code&gt;[Install]&lt;/code&gt; section in the service definition.  Please note that the sockets are to be enabled; the service itself is to be left untouched.&lt;/p&gt;

&lt;p&gt;Verifying status of the GPG agent can be done using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl status &lt;span class="nt"&gt;--user&lt;/span&gt; gpg-agent.socket
&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl status &lt;span class="nt"&gt;--user&lt;/span&gt; gpg-agent-ssh.socket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although the service is now running, the environment shows an incorrect value for &lt;code&gt;SSH_AUTH_SOCK&lt;/code&gt; (&lt;code&gt;/run/user/&amp;lt;uid&amp;gt;/keyring/ssh&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing SSH_AUTH_SOCK
&lt;/h2&gt;

&lt;p&gt;There are several configurations blocking successful use of &lt;code&gt;gpg-agent&lt;/code&gt; for SSH, causing the value of &lt;code&gt;SSH_AUTH_SOCK&lt;/code&gt; to be incorrect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disable &lt;code&gt;ssh-agent&lt;/code&gt; user service
&lt;/h3&gt;

&lt;p&gt;If it is enabled, this service needs to be disabled, as it is conflicting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl disable &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; ssh-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Disable Xsession.options ssh-agent
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Xsession&lt;/code&gt; script tries to start an &lt;code&gt;ssh-agent&lt;/code&gt;. This can be disabled by modifying &lt;code&gt;/etc/X11/Xsession.options&lt;/code&gt; and &lt;code&gt;/etc/X11/Xsession.options.d/*.conf&lt;/code&gt;, making sure the last file loaded contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;no-use-ssh-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is best achieved by creating a file named &lt;code&gt;/etc/X11/Xsession.options.d/zz-no-ssh-agent.conf&lt;/code&gt; with that content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Disable GNOME Keyring (gnome-keyring-ssh.desktop)
&lt;/h3&gt;

&lt;p&gt;GNOME Keyring tries to start an SSH agent if none is running. The way to disable this is by executing the following commands - which are different from those published all around:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cp /etc/xdg/autostart/gnome-keyring-ssh.desktop ~/.config/autostart/gnome-keyring-ssh.desktop
$ echo "X-GNOME-Autostart-enabled=false" &amp;gt;&amp;gt; ~/.config/autostart/gnome-keyring-ssh.desktop
$ echo "Hidden=true" &amp;gt;&amp;gt; ~/.config/autostart/gnome-keyring-ssh.desktop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "Hidden=true" addition is advertized all around the web, but didn't work for me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting SSH_AUTH_SOCK
&lt;/h3&gt;

&lt;p&gt;Using systemd to manage &lt;code&gt;gpg-agent&lt;/code&gt; has one drawback: systemd doesn't set environment variables in the user shell session.  This can be solved by adding this snippet to the user's &lt;code&gt;bashrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# to be appended to ~/.bashrc&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SSH_AUTH_SOCK&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;
&lt;span class="k"&gt;then
  if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"/run/user/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/gnupg/S.gpg-agent.ssh"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;
  &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SSH_AUTH_SOCK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/run/user/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/gnupg/S.gpg-agent.ssh"&lt;/span&gt;
  &lt;span class="k"&gt;fi
fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Yubikey and smart card support with private keys on the key or card does not come out of the box, even in this day and age, but with a bit of configuration, setting up private keys on a smart card and making it work under GNOME, is doable.&lt;/p&gt;

</description>
      <category>ssh</category>
      <category>gpg</category>
      <category>systemd</category>
      <category>yubikey</category>
    </item>
    <item>
      <title>Server access with SSH certificates - deep dive</title>
      <dc:creator>Erik Huelsmann</dc:creator>
      <pubDate>Sat, 30 Mar 2024 17:07:21 +0000</pubDate>
      <link>https://dev.to/ehuelsmann/server-access-with-ssh-certificates-deep-dive-4h05</link>
      <guid>https://dev.to/ehuelsmann/server-access-with-ssh-certificates-deep-dive-4h05</guid>
      <description>&lt;p&gt;There are a growing number of articles around which explain about the setup and use of SSH certificates, like &lt;a href="https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Certificate-based_Authentication"&gt;the Wikibooks Certificate-based Authentication cookbook&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;This article goes into detail where the others stop: Most articles describe how the principal in the certificate (&lt;code&gt;-n&lt;/code&gt; argument to &lt;code&gt;ssh-keygen&lt;/code&gt; when signing the user's key) needs to be set to the name of the user on the target host. There are however many more options that can be used on the server as well as in the certificate to manage access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced principals
&lt;/h2&gt;

&lt;p&gt;By default, OpenSSH requires the name of the user logging in to be among the principals in the certificate. That is, if certificate based authentication is used, 'bob' needs to be in the list of principals to be able to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ssh bob@server01.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next to this default, servers have 3 mechanisms for setting up more advanced authentication setups using principals.&lt;/p&gt;

&lt;h3&gt;
  
  
  AuthorizedPrincipalsFile
&lt;/h3&gt;

&lt;p&gt;Using this directive, a global or per-user list of principals can be configured for access to the server. That is to say that if the server is configured with an &lt;code&gt;authorized_principals&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# /etc/ssh/sshd_config

# for a global configuration:
AuthorizedPrincipalsFile /etc/ssh/authorized_principals

# for per-user configuration, relative to $HOME:
AuthorizedPrincipalsFile .ssh/authorized_principals
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which contains&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;access-any-user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, if bob has a certificate named &lt;code&gt;any_bob&lt;/code&gt; with the &lt;code&gt;access-any-user&lt;/code&gt; principal, he can authenticate to the server as &lt;em&gt;any&lt;/em&gt; user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bob@client&lt;span class="nv"&gt;$ &lt;/span&gt;ssh &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;CertificateFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;any_bob-cert.pub &lt;span class="nt"&gt;-i&lt;/span&gt; any_bob sshd@server01.example.com
This account is currently not available.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response &lt;code&gt;This account is currently not available.&lt;/code&gt; indicates the authentication was successful and the &lt;code&gt;nologin&lt;/code&gt; shell was executed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remark&lt;/strong&gt;: Using the AuthorizedPrincipalsFile directive disables the default behaviour to accept certificates listing the target username among the principals.&lt;/p&gt;

&lt;h4&gt;
  
  
  Per-principal command restriction
&lt;/h4&gt;

&lt;p&gt;The authorized principals file supports the same options as the authorized keys file does. Assuming &lt;code&gt;server01&lt;/code&gt; has a user named &lt;code&gt;wacky&lt;/code&gt; with a regular login shell, if we change &lt;code&gt;/etc/ssh/authorized_principals&lt;/code&gt; to contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;command="/usr/bin/date" access-any-user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bob@client&lt;span class="nv"&gt;$ &lt;/span&gt;ssh &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;CertificateFile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;any_bob-cert.pub &lt;span class="nt"&gt;-i&lt;/span&gt; any_bob wacky@server01.example.com
Sat Mar 30 15:29:44 CET 2024
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The source from which is being connected can be restricted using this method using the &lt;code&gt;from=&lt;/code&gt; option. See for more options the documentation of the &lt;code&gt;authorized_keys&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Certificate based restrictions
&lt;/h2&gt;

&lt;p&gt;Certificates can come with their own restrictions, independent of the restrictions specified by the server. The ones to highlight here are &lt;code&gt;force-command&lt;/code&gt; and &lt;code&gt;source-address&lt;/code&gt;. In case a &lt;code&gt;force-command&lt;/code&gt; restriction in the certificate conflicts with the &lt;code&gt;command&lt;/code&gt; restriction in the authorized principals file (i.e. they are not the same string), the mechanism is considered a mismatch (and the next mechanism - e.g. password based - is tried).&lt;/p&gt;

&lt;h2&gt;
  
  
  Certificate identity (&lt;code&gt;-I&lt;/code&gt;) and sequence numbers (&lt;code&gt;-z&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;Although most sources hostnames for host certificates and &lt;code&gt;&amp;lt;user&amp;gt;@&amp;lt;host&amp;gt;&lt;/code&gt; for user certificates, these can be any string value. They serve two purposes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To identify the certificate that was presented during authentication, in the system logs (syslog or journalctl); and&lt;/li&gt;
&lt;li&gt;To identify the certificate in the Key Revocation List (KRL) &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Many articles don't specify a sequence number, but specifying one is definitely desirable to be able to revoke specific certificates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic authorization of principals
&lt;/h2&gt;

&lt;p&gt;The configuration option &lt;code&gt;AuthorizedPrincipalsCommand&lt;/code&gt; is a global setting which may be used to configure dynamic authorized principal list generation using an external command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AuthorizedPrincipalsCommand /usr/local/bin/dynamic-principals "%u %s"
AuthorizedPrincipalsCommandUser dedicateduser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;sshd_config&lt;/code&gt; man page lists the supported tokens. Each returned line on standard output must conform to the same requirements as the lines from a static authorized principals file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To authenticate servers to clients:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A host certificate authority (CA) key pair&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A host CA's &lt;strong&gt;public key&lt;/strong&gt; &lt;em&gt;deployed to clients&lt;/em&gt;; configured using the &lt;code&gt;@cert-authority&lt;/code&gt; known_hosts-marker either through&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;global configuration (&lt;code&gt;/etc/ssh/ssh_known_hosts&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;user specific configuration (&lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;In case of a user-specified CA in authorized_keys, a principals list needs to be specified with the &lt;code&gt;principals=&lt;/code&gt; option.&lt;/em&gt;&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To authenticate clients to servers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A client CA key pair&lt;/li&gt;
&lt;li&gt;A client CA's &lt;strong&gt;public key&lt;/strong&gt; &lt;em&gt;deployed to servers&lt;/em&gt;; configured through &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt; using the &lt;code&gt;TrustedUserCAKeys&lt;/code&gt; configuration directive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: neither the client CA nor the host CA require a certificate of their own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Although by default the target user name must be among the principals in the certificate, this is not a hard requirement: principals can be listed statically or dynamically on the server resulting in a successful authentication when a non-empty intersection between the server and certificate principals exists. This allows for a setup where principals define roles rather than login accounts.&lt;/p&gt;

&lt;p&gt;Using the concepts presented in this article (especially the - certificate-based - command restriction) in combination with command restrictions in e.g. &lt;code&gt;sudo&lt;/code&gt; opens opportunities for fine-grained control over user and admin access.&lt;/p&gt;

</description>
      <category>security</category>
      <category>ssh</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
