feat: add recorder and enforceRecorder support in SSH ACL

Signed-off-by: Julian Mundhahs <github@mundhahs.dev>
This commit is contained in:
Julian Mundhahs 2024-02-24 09:54:01 +01:00 committed by Julian Mundhahs
parent 1d3eae8861
commit 04c7c5b0b6
3 changed files with 49 additions and 9 deletions

View file

@ -343,6 +343,28 @@ func (pol *ACLPolicy) generateSSHRules(
continue continue
} }
recs := make([]netip.AddrPort, 0)
for innerIndex, rec := range sshACL.Recorder {
recSet, err := pol.ExpandAlias(append(peers, node), rec)
if err != nil {
log.Error().
Msgf("Error parsing SSH %d, Recorder %d", index, innerIndex)
return nil, err
}
// ExpandAlias has expanded possible subnets; all prefixes are single IPs
for _, rec := range recSet.Prefixes() {
recs = append(recs, netip.AddrPortFrom(rec.Addr(), 80))
}
}
action.Recorders = recs
if sshACL.EnforceRecorder {
action.OnRecordingFailure = &tailcfg.SSHRecorderFailureAction{
RejectSessionWithMessage: "# Failed to start session recording.",
TerminateSessionWithMessage: "# Failed to start session recording.",
}
}
principals := make([]*tailcfg.SSHPrincipal, 0, len(sshACL.Sources)) principals := make([]*tailcfg.SSHPrincipal, 0, len(sshACL.Sources))
for innerIndex, rawSrc := range sshACL.Sources { for innerIndex, rawSrc := range sshACL.Sources {
if isWildcard(rawSrc) { if isWildcard(rawSrc) {

View file

@ -2956,7 +2956,11 @@ func TestSSHRules(t *testing.T) {
SSHUsers: map[string]string{ SSHUsers: map[string]string{
"autogroup:nonroot": "=", "autogroup:nonroot": "=",
}, },
Action: &tailcfg.SSHAction{Accept: true, AllowLocalPortForwarding: true}, Action: &tailcfg.SSHAction{
Accept: true,
AllowLocalPortForwarding: true,
Recorders: []netip.AddrPort{},
},
}, },
{ {
SSHUsers: map[string]string{ SSHUsers: map[string]string{
@ -2967,7 +2971,11 @@ func TestSSHRules(t *testing.T) {
Any: true, Any: true,
}, },
}, },
Action: &tailcfg.SSHAction{Accept: true, AllowLocalPortForwarding: true}, Action: &tailcfg.SSHAction{
Accept: true,
AllowLocalPortForwarding: true,
Recorders: []netip.AddrPort{},
},
}, },
{ {
Principals: []*tailcfg.SSHPrincipal{ Principals: []*tailcfg.SSHPrincipal{
@ -2978,7 +2986,11 @@ func TestSSHRules(t *testing.T) {
SSHUsers: map[string]string{ SSHUsers: map[string]string{
"autogroup:nonroot": "=", "autogroup:nonroot": "=",
}, },
Action: &tailcfg.SSHAction{Accept: true, AllowLocalPortForwarding: true}, Action: &tailcfg.SSHAction{
Accept: true,
AllowLocalPortForwarding: true,
Recorders: []netip.AddrPort{},
},
}, },
{ {
SSHUsers: map[string]string{ SSHUsers: map[string]string{
@ -2989,7 +3001,11 @@ func TestSSHRules(t *testing.T) {
Any: true, Any: true,
}, },
}, },
Action: &tailcfg.SSHAction{Accept: true, AllowLocalPortForwarding: true}, Action: &tailcfg.SSHAction{
Accept: true,
AllowLocalPortForwarding: true,
Recorders: []netip.AddrPort{},
},
}, },
}, },
}, },

View file

@ -53,11 +53,13 @@ type AutoApprovers struct {
// SSH controls who can ssh into which machines. // SSH controls who can ssh into which machines.
type SSH struct { type SSH struct {
Action string `json:"action" yaml:"action"` Action string `json:"action" yaml:"action"`
Sources []string `json:"src" yaml:"src"` Sources []string `json:"src" yaml:"src"`
Destinations []string `json:"dst" yaml:"dst"` Destinations []string `json:"dst" yaml:"dst"`
Users []string `json:"users" yaml:"users"` Users []string `json:"users" yaml:"users"`
CheckPeriod string `json:"checkPeriod,omitempty" yaml:"checkPeriod,omitempty"` CheckPeriod string `json:"checkPeriod,omitempty" yaml:"checkPeriod,omitempty"`
Recorder []string `json:"recorder,omitempty" yaml:"recorder,omitempty"`
EnforceRecorder bool `json:"enforceRecorder,omitempty" yaml:"enforceRecorder,omitempty"`
} }
// UnmarshalJSON allows to parse the Hosts directly into netip objects. // UnmarshalJSON allows to parse the Hosts directly into netip objects.