diff --git a/commands/login.go b/commands/login.go index b307421f..e18bbd4e 100644 --- a/commands/login.go +++ b/commands/login.go @@ -478,9 +478,11 @@ func (l *LoginCmd) login(ctx context.Context, provider providers.OpenIdProvider, } } - // If principals is empty the server does not enforce any principal. The OPK - // verifier should use policy to make this decision. - principals := []string{} + // If principals field is empty sshd automatically rejects the SSH certificate. + // We use opkssh-wildcard as placeholder so that we can allow the OPK + // verifier to make this policy decision instead of sshd. + // See https://github.com/openpubkey/opkssh/pull/513 + principals := []string{"opkssh-wildcard"} certBytes, seckeySshPem, err := createSSHCertWithAccessToken(pkt, accessToken, signer, principals) if err != nil { return nil, fmt.Errorf("failed to generate SSH cert: %w", err) diff --git a/commands/verify.go b/commands/verify.go index 9f30f81e..350e0203 100644 --- a/commands/verify.go +++ b/commands/verify.go @@ -21,6 +21,7 @@ import ( "fmt" "io/fs" "net/http" + "strings" "github.com/openpubkey/openpubkey/pktoken" "github.com/openpubkey/openpubkey/verifier" @@ -124,8 +125,19 @@ func (v *VerifyCmd) AuthorizedKeysCommand(ctx context.Context, userArg string, t // sshd expects the public key in the cert, not the cert itself. This // public key is key of the CA that signs the cert, in our setting there // is no CA. - pubkeyBytes := ssh.MarshalAuthorizedKey(cert.SshCert.SignatureKey) - return "cert-authority " + string(pubkeyBytes), nil + pubkeyBytes := strings.TrimSpace(string(ssh.MarshalAuthorizedKey(cert.SshCert.SignatureKey))) + + principals := strings.Join(cert.SshCert.ValidPrincipals, ",") + if principals != "" { + // Makes sshd trust the principals in the certificate. + // This is needed to emulate a principal wildcard in an SSH cert. + // OpenSSH intentionally broke the old way of doing SSH cert principal + // wildcards requiring OPKSSH to use this approach instead. + // See https://github.com/openpubkey/opkssh/pull/513 + return fmt.Sprintf("cert-authority,principals=\"%s\" %s", principals, pubkeyBytes), nil + } + + return fmt.Sprintf("cert-authority %s", pubkeyBytes), nil } } } diff --git a/commands/verify_test.go b/commands/verify_test.go index f72f05cd..05b7253b 100644 --- a/commands/verify_test.go +++ b/commands/verify_test.go @@ -171,7 +171,7 @@ func TestAuthorizedKeysCommand(t *testing.T) { } else { require.NoError(t, err) - expectedPubkeyList := "cert-authority ecdsa-sha2-nistp256" + expectedPubkeyList := "cert-authority,principals=\"guest,dev\" ecdsa-sha2-nistp256" require.Contains(t, pubkeyList, expectedPubkeyList) } })