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
}
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))
for innerIndex, rawSrc := range sshACL.Sources {
if isWildcard(rawSrc) {

View file

@ -2956,7 +2956,11 @@ func TestSSHRules(t *testing.T) {
SSHUsers: map[string]string{
"autogroup:nonroot": "=",
},
Action: &tailcfg.SSHAction{Accept: true, AllowLocalPortForwarding: true},
Action: &tailcfg.SSHAction{
Accept: true,
AllowLocalPortForwarding: true,
Recorders: []netip.AddrPort{},
},
},
{
SSHUsers: map[string]string{
@ -2967,7 +2971,11 @@ func TestSSHRules(t *testing.T) {
Any: true,
},
},
Action: &tailcfg.SSHAction{Accept: true, AllowLocalPortForwarding: true},
Action: &tailcfg.SSHAction{
Accept: true,
AllowLocalPortForwarding: true,
Recorders: []netip.AddrPort{},
},
},
{
Principals: []*tailcfg.SSHPrincipal{
@ -2978,7 +2986,11 @@ func TestSSHRules(t *testing.T) {
SSHUsers: map[string]string{
"autogroup:nonroot": "=",
},
Action: &tailcfg.SSHAction{Accept: true, AllowLocalPortForwarding: true},
Action: &tailcfg.SSHAction{
Accept: true,
AllowLocalPortForwarding: true,
Recorders: []netip.AddrPort{},
},
},
{
SSHUsers: map[string]string{
@ -2989,7 +3001,11 @@ func TestSSHRules(t *testing.T) {
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.
type SSH struct {
Action string `json:"action" yaml:"action"`
Sources []string `json:"src" yaml:"src"`
Destinations []string `json:"dst" yaml:"dst"`
Users []string `json:"users" yaml:"users"`
CheckPeriod string `json:"checkPeriod,omitempty" yaml:"checkPeriod,omitempty"`
Action string `json:"action" yaml:"action"`
Sources []string `json:"src" yaml:"src"`
Destinations []string `json:"dst" yaml:"dst"`
Users []string `json:"users" yaml:"users"`
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.