Updates #3802 Fixes #3960 Change-Id: Ieda2007d462ddce6c217b958167417ae9755774e Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>main
parent
66f5aa6814
commit
e1e20f6d39
@ -0,0 +1,157 @@ |
||||
// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package tailssh |
||||
|
||||
import ( |
||||
"testing" |
||||
"time" |
||||
|
||||
"inet.af/netaddr" |
||||
"tailscale.com/tailcfg" |
||||
) |
||||
|
||||
func TestMatchRule(t *testing.T) { |
||||
someAction := new(tailcfg.SSHAction) |
||||
tests := []struct { |
||||
name string |
||||
rule *tailcfg.SSHRule |
||||
ctx *sshContext |
||||
wantErr error |
||||
wantUser string |
||||
}{ |
||||
{ |
||||
name: "nil-rule", |
||||
rule: nil, |
||||
wantErr: errNilRule, |
||||
}, |
||||
{ |
||||
name: "nil-action", |
||||
rule: &tailcfg.SSHRule{}, |
||||
wantErr: errNilAction, |
||||
}, |
||||
{ |
||||
name: "expired", |
||||
rule: &tailcfg.SSHRule{ |
||||
Action: someAction, |
||||
RuleExpires: timePtr(time.Unix(100, 0)), |
||||
}, |
||||
ctx: &sshContext{now: time.Unix(200, 0)}, |
||||
wantErr: errRuleExpired, |
||||
}, |
||||
{ |
||||
name: "no-principal", |
||||
rule: &tailcfg.SSHRule{ |
||||
Action: someAction, |
||||
}, |
||||
wantErr: errPrincipalMatch, |
||||
}, |
||||
{ |
||||
name: "no-user-match", |
||||
rule: &tailcfg.SSHRule{ |
||||
Action: someAction, |
||||
Principals: []*tailcfg.SSHPrincipal{{Any: true}}, |
||||
}, |
||||
ctx: &sshContext{sshUser: "alice"}, |
||||
wantErr: errUserMatch, |
||||
}, |
||||
{ |
||||
name: "ok-wildcard", |
||||
rule: &tailcfg.SSHRule{ |
||||
Action: someAction, |
||||
Principals: []*tailcfg.SSHPrincipal{{Any: true}}, |
||||
SSHUsers: map[string]string{ |
||||
"*": "ubuntu", |
||||
}, |
||||
}, |
||||
ctx: &sshContext{sshUser: "alice"}, |
||||
wantUser: "ubuntu", |
||||
}, |
||||
{ |
||||
name: "ok-wildcard-and-nil-principal", |
||||
rule: &tailcfg.SSHRule{ |
||||
Action: someAction, |
||||
Principals: []*tailcfg.SSHPrincipal{ |
||||
nil, // don't crash on this
|
||||
{Any: true}, |
||||
}, |
||||
SSHUsers: map[string]string{ |
||||
"*": "ubuntu", |
||||
}, |
||||
}, |
||||
ctx: &sshContext{sshUser: "alice"}, |
||||
wantUser: "ubuntu", |
||||
}, |
||||
{ |
||||
name: "ok-exact", |
||||
rule: &tailcfg.SSHRule{ |
||||
Action: someAction, |
||||
Principals: []*tailcfg.SSHPrincipal{{Any: true}}, |
||||
SSHUsers: map[string]string{ |
||||
"*": "ubuntu", |
||||
"alice": "thealice", |
||||
}, |
||||
}, |
||||
ctx: &sshContext{sshUser: "alice"}, |
||||
wantUser: "thealice", |
||||
}, |
||||
{ |
||||
name: "no-users-for-reject", |
||||
rule: &tailcfg.SSHRule{ |
||||
Principals: []*tailcfg.SSHPrincipal{{Any: true}}, |
||||
Action: &tailcfg.SSHAction{Reject: true}, |
||||
}, |
||||
ctx: &sshContext{sshUser: "alice"}, |
||||
}, |
||||
{ |
||||
name: "match-principal-node-ip", |
||||
rule: &tailcfg.SSHRule{ |
||||
Action: someAction, |
||||
Principals: []*tailcfg.SSHPrincipal{{NodeIP: "1.2.3.4"}}, |
||||
SSHUsers: map[string]string{"*": "ubuntu"}, |
||||
}, |
||||
ctx: &sshContext{srcIP: netaddr.MustParseIP("1.2.3.4")}, |
||||
wantUser: "ubuntu", |
||||
}, |
||||
{ |
||||
name: "match-principal-node-id", |
||||
rule: &tailcfg.SSHRule{ |
||||
Action: someAction, |
||||
Principals: []*tailcfg.SSHPrincipal{{Node: "some-node-ID"}}, |
||||
SSHUsers: map[string]string{"*": "ubuntu"}, |
||||
}, |
||||
ctx: &sshContext{node: &tailcfg.Node{StableID: "some-node-ID"}}, |
||||
wantUser: "ubuntu", |
||||
}, |
||||
{ |
||||
name: "match-principal-userlogin", |
||||
rule: &tailcfg.SSHRule{ |
||||
Action: someAction, |
||||
Principals: []*tailcfg.SSHPrincipal{{UserLogin: "foo@bar.com"}}, |
||||
SSHUsers: map[string]string{"*": "ubuntu"}, |
||||
}, |
||||
ctx: &sshContext{uprof: &tailcfg.UserProfile{LoginName: "foo@bar.com"}}, |
||||
wantUser: "ubuntu", |
||||
}, |
||||
} |
||||
for _, tt := range tests { |
||||
t.Run(tt.name, func(t *testing.T) { |
||||
got, gotUser, err := matchRule(tt.rule, tt.ctx) |
||||
if err != tt.wantErr { |
||||
t.Errorf("err = %v; want %v", err, tt.wantErr) |
||||
} |
||||
if gotUser != tt.wantUser { |
||||
t.Errorf("user = %q; want %q", gotUser, tt.wantUser) |
||||
} |
||||
if err == nil && got == nil { |
||||
t.Errorf("expected non-nil action on success") |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
|
||||
func timePtr(t time.Time) *time.Time { return &t } |
||||
Loading…
Reference in new issue