mirror of
https://github.com/pomerium/pomerium.git
synced 2025-08-02 16:30:17 +02:00
ssh: improve 'whoami' format (#5714)
Old: ``` User ID: xxx Session ID: xxx Expires at: 2025-07-10 08:39:40.64992461 +0000 UTC Claims: aud: [xxx] email: [foo@bar.com] email_verified: [true] exp: [1.75212238e+09] family_name: [bar] given_name: [foo] iat: [1.75208638e+09] iss: [https://example.com] name: [Foo Bar] nickname: [foobar] picture: [https://example.com] sub: [xxx] updated_at: [2025-07-09T18:12:15.226Z] ``` New: ``` User ID: xxx Session ID: xxx Expires at: 2025-07-10 11:23:27.641004885 +0000 UTC (in 13h59m57s) Claims: aud: "xxx" email: "foo@bar.com" email_verified: true exp: 2025-07-10 07:23:27 +0000 UTC (in 9h59m56s) family_name: "bar" given_name: "foo" iat: 2025-07-09 21:23:27 +0000 UTC (4s ago) iss: "https://example.com" name: "Foo Bar" nickname: "foobar" picture: "https://example.com" sub: "xxx" updated_at: "2025-07-09T18:12:15.226Z" ```
This commit is contained in:
parent
88c7a6537a
commit
33abea3ea6
4 changed files with 64 additions and 32 deletions
|
@ -337,7 +337,7 @@ func (state state) GetUserInfo(users map[string]*User) *userInfo {
|
|||
for _, u := range users {
|
||||
if u.Email == state.Email {
|
||||
userInfo.Subject = u.ID
|
||||
userInfo.Name = u.FirstName + " " + u.LastName
|
||||
userInfo.Name = strings.TrimSpace(u.FirstName + " " + u.LastName)
|
||||
userInfo.FamilyName = u.LastName
|
||||
userInfo.GivenName = u.FirstName
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ import (
|
|||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"text/template"
|
||||
"fmt"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
oteltrace "go.opentelemetry.io/otel/trace"
|
||||
|
@ -258,9 +259,48 @@ func (a *Auth) FormatSession(ctx context.Context, info StreamAuthInfo) ([]byte,
|
|||
return nil, err
|
||||
}
|
||||
var b bytes.Buffer
|
||||
err = sessionInfoTmpl.Execute(&b, session)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
fmt.Fprintf(&b, "User ID: %s\n", session.UserId)
|
||||
fmt.Fprintf(&b, "Session ID: %s\n", sessionID)
|
||||
fmt.Fprintf(&b, "Expires at: %s (in %s)\n",
|
||||
session.ExpiresAt.AsTime().String(),
|
||||
time.Until(session.ExpiresAt.AsTime()).Round(time.Second))
|
||||
fmt.Fprintf(&b, "Claims:\n")
|
||||
keys := make([]string, 0, len(session.Claims))
|
||||
for key := range session.Claims {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
slices.Sort(keys)
|
||||
for _, key := range keys {
|
||||
fmt.Fprintf(&b, " %s: ", key)
|
||||
vs := session.Claims[key].AsSlice()
|
||||
if len(vs) != 1 {
|
||||
b.WriteRune('[')
|
||||
}
|
||||
if len(vs) == 1 {
|
||||
switch key {
|
||||
case "iat":
|
||||
d, _ := vs[0].(float64)
|
||||
t := time.Unix(int64(d), 0)
|
||||
fmt.Fprintf(&b, "%s (%s ago)", t, time.Since(t).Round(time.Second))
|
||||
case "exp":
|
||||
d, _ := vs[0].(float64)
|
||||
t := time.Unix(int64(d), 0)
|
||||
fmt.Fprintf(&b, "%s (in %s)", t, time.Until(t).Round(time.Second))
|
||||
default:
|
||||
fmt.Fprintf(&b, "%#v", vs[0])
|
||||
}
|
||||
} else if len(vs) > 1 {
|
||||
for i, v := range vs {
|
||||
fmt.Fprintf(&b, "%#v", v)
|
||||
if i < len(vs)-1 {
|
||||
b.WriteString(", ")
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(vs) != 1 {
|
||||
b.WriteRune(']')
|
||||
}
|
||||
b.WriteRune('\n')
|
||||
}
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
@ -375,13 +415,3 @@ func sshRequestFromStreamAuthInfo(info StreamAuthInfo) (*Request, error) {
|
|||
LogOnlyIfDenied: info.InitialAuthComplete,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var sessionInfoTmpl = template.Must(template.New("session-info").Parse(`
|
||||
User ID: {{.UserId}}
|
||||
Session ID: {{.Id}}
|
||||
Expires at: {{.ExpiresAt.AsTime}}
|
||||
Claims:
|
||||
{{- range $k, $v := .Claims }}
|
||||
{{ $k }}: {{ $v.AsSlice }}
|
||||
{{- end }}
|
||||
`))
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -361,6 +362,7 @@ func TestFormatSession(t *testing.T) {
|
|||
assert.ErrorContains(t, err, "invalid public key fingerprint")
|
||||
})
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
exp := time.Now().Add(1 * time.Minute)
|
||||
client := fakeDataBrokerServiceClient{
|
||||
get: func(
|
||||
_ context.Context, in *databroker.GetRequest, _ ...grpc.CallOption,
|
||||
|
@ -379,7 +381,7 @@ func TestFormatSession(t *testing.T) {
|
|||
Data: protoutil.NewAny(&session.Session{
|
||||
Id: expectedID,
|
||||
UserId: "USER-ID",
|
||||
ExpiresAt: ×tamppb.Timestamp{Seconds: 1750965358},
|
||||
ExpiresAt: timestamppb.New(exp),
|
||||
Claims: claims.ToPB(),
|
||||
}),
|
||||
},
|
||||
|
@ -392,14 +394,14 @@ func TestFormatSession(t *testing.T) {
|
|||
}
|
||||
b, err := a.FormatSession(t.Context(), info)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, string(b), `
|
||||
assert.Regexp(t, `
|
||||
User ID: USER-ID
|
||||
Session ID: sshkey-SHA256:QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVoxMjM0NTY
|
||||
Expires at: 2025-06-26 19:15:58 +0000 UTC
|
||||
Expires at: .* \(in 1m0s\)
|
||||
Claims:
|
||||
foo: [bar baz]
|
||||
quux: [42]
|
||||
`)
|
||||
foo: \["bar", "baz"\]
|
||||
quux: 42
|
||||
`[1:], string(b))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -331,18 +331,18 @@ func (s *SSHTestSuite) TestWhoami() {
|
|||
s.Regexp(s.executeTemplate(`
|
||||
User ID: .*
|
||||
Session ID: sshkey-{{.PublicKeyFingerprint | quoteMeta}}
|
||||
Expires at: .*
|
||||
Expires at: .* \(in \d+h\d+m\d+s\)
|
||||
Claims:
|
||||
aud: \[CLIENT_ID\]
|
||||
email: \[{{.Email | quoteMeta}}\]
|
||||
exp: \[.*\]
|
||||
family_name: \[\]
|
||||
given_name: \[\]
|
||||
iat: \[.*\]
|
||||
iss: \[https://mock-idp\..*\]
|
||||
name: \[ \]
|
||||
sub: \[.*\]
|
||||
`), string(output))
|
||||
aud: "CLIENT_ID"
|
||||
email: "{{.Email | quoteMeta}}"
|
||||
exp: .* \(in \d+h\d+m\d+s\)
|
||||
family_name: ""
|
||||
given_name: ""
|
||||
iat: .* \(\d+s ago\)
|
||||
iss: "https://mock-idp\..*"
|
||||
name: ""
|
||||
sub: ".*"
|
||||
`[1:]), string(output))
|
||||
}
|
||||
|
||||
func TestSSH(t *testing.T) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue