Hi, We're developing an open source project that uses SSH certificates. We issue short lived certificates (few minutes) to execute commands on behalf of users. We have a use case where we need to issue certificates with 10 days validity and store them, so we put a command inside them: ssh-keygen -s ca-key -I certN -n user -O force-command="wget something" -V +10d user-key.pub and it works as expected. This way, if the certificate is stolen, it can only be used to execute that command (also the CA is only trusted from some hosts, no root login, etc). We also want to use "ForceCommand" option on the server (inside a "Match" section) to put a wrapper that checks commands executed for this CA. If a rogue certificate is issued, at least we can control what is executed. However, as the command is embedded inside the certificate, the server passes an empty "SSH_ORIGINAL_COMMAND" to the wrapper. I couldn't find any additional option or environment variable for this case. We can pass the command when the connection is established, but it defeats the purpose of having the certificate's "force-command". So, is there a way the wrapper could get the command embedded inside a certificate? As a side note, more information about the certificate (issue and expiration time) could be useful for auditing. It would be useful too if the server could log it (aside from CA, certificate serial, etc), but couldn't find any option either. Regards, Ale
On 23/06/2020 16:11, Alejandro Dabin wrote:> As a side note, more information about the certificate (issue and > expiration time) could be useful for auditing. It would be useful too if > the server could log it (aside from CA, certificate serial, etc), but > couldn't find any option either.AuthorizedPrincipalsCommand can use a number of tokens which are expanded: ?????????? %%??? A literal `%'. ?????????? %F??? The fingerprint of the CA key. ?????????? %f??? The fingerprint of the key or certificate. ?????????? %h??? The home directory of the user. ?????????? %i??? The key ID in the certificate. ?????????? %K??? The base64-encoded CA key. ?????????? %k??? The base64-encoded key or certificate for authentication. ?????????? %s??? The serial number of the certificate. ?????????? %T??? The type of the CA key. ?????????? %t??? The key or certificate type. ?????????? %U??? The numeric user ID of the target user. ?????????? %u??? The username.
On Tue, 23 Jun 2020, Alejandro Dabin wrote:> Hi, > We're developing an open source project that uses SSH certificates. We > issue short lived certificates (few minutes) to execute commands on behalf > of users. We have a use case where we need to issue certificates with 10 > days validity and store them, so we put a command inside them: > > ssh-keygen -s ca-key -I certN -n user -O force-command="wget something" -V > +10d user-key.pub > > and it works as expected. This way, if the certificate is stolen, it can > only be used to execute that command (also the CA is only trusted from some > hosts, no root login, etc). > > We also want to use "ForceCommand" option on the server (inside a "Match" > section) to put a wrapper that checks commands executed for this CA. If a > rogue certificate is issued, at least we can control what is executed. > However, as the command is embedded inside the certificate, the server > passes an empty "SSH_ORIGINAL_COMMAND" to the wrapper. I couldn't find any > additional option or environment variable for this case. We can pass the > command when the connection is established, but it defeats the purpose of > having the certificate's "force-command". > > So, is there a way the wrapper could get the command embedded inside a > certificate?I think your best avenue would be to set ExposeAuthInfo=yes in sshd_config (note: requires a relatively recent sshd) and parse it out of the certificate listed in $SSH_USER_AUTH. E.g. grep "^publickey .*cert[a-z0-9-]*@openssh.com" $SSH_USER_AUTH \ | awk '{print $2 " " $3}' | ssh-keygen -Lf -> As a side note, more information about the certificate (issue and > expiration time) could be useful for auditing. It would be useful too if > the server could log it (aside from CA, certificate serial, etc), but > couldn't find any option either.No, the logging tries to balance between usefulness and brevity. I'm not sure why expiry information would be useful there - I would have thought that it's either it's good and accepted or bad and not... -d
On 23/06/20, Alejandro Dabin (aledabin at gmail.com) wrote:> As a side note, more information about the certificate (issue and > expiration time) could be useful for auditing. It would be useful too if > the server could log it (aside from CA, certificate serial, etc), but > couldn't find any option either.The identifier can be overloaded to have arbitrary information shown in the audit log. I can't recall if you need to set LogLevel to something above INFO. Eg: https://github.com/rorycl/sshagentca/blob/65f726c8480877366cfe13235247a67f0702393d/agentcert.go#L35 Rory
On 23 jun. 2020 a las 23:21, Damien Miller wrote:> I think your best avenue would be to set ExposeAuthInfo=yes in > sshd_config (note: requires a relatively recent sshd) and parse it out > of the certificate listed in $SSH_USER_AUTH. E.g. > > grep "^publickey .*cert[a-z0-9-]*@openssh.com" $SSH_USER_AUTH \ > | awk '{print $2 " " $3}' | ssh-keygen -Lf -"ExposeAuthInfo" solves our use case because it allows to read the certificate with user privilegies. It requires sshd >= 7.6, I was reading the manual on my distro which uses 7.4. Thank you all for your time, and for the great OpenSSH suite! Regards, Ale