tailscale/drive/remote_permissions.go
Percy Wegmann 955ad12489 ipn/ipnlocal: only show Taildrive peers to which ACLs grant us access
This improves convenience and security.

* Convenience - no need to see nodes that can't share anything with you.
* Security - malicious nodes can't expose shares to peers that aren't
             allowed to access their shares.

Updates tailscale/corp#19432

Signed-off-by: Percy Wegmann <percy@tailscale.com>
2024-04-24 17:49:04 -05:00

66 lines
1.3 KiB
Go

// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package drive
import (
"encoding/json"
"fmt"
)
type Permission uint8
const (
PermissionNone Permission = iota
PermissionReadOnly
PermissionReadWrite
)
const (
accessReadOnly = "ro"
accessReadWrite = "rw"
wildcardShare = "*"
)
// Permissions represents the set of permissions for a given principal to a
// set of shares.
type Permissions map[string]Permission
type grant struct {
Shares []string
Access string
}
// ParsePermissions builds a Permissions map from a lis of raw grants.
func ParsePermissions(rawGrants [][]byte) (Permissions, error) {
permissions := make(Permissions)
for _, rawGrant := range rawGrants {
var g grant
err := json.Unmarshal(rawGrant, &g)
if err != nil {
return nil, fmt.Errorf("unmarshal raw grants %s: %v", rawGrant, err)
}
for _, share := range g.Shares {
existingPermission := permissions[share]
permission := PermissionReadOnly
if g.Access == accessReadWrite {
permission = PermissionReadWrite
}
if permission > existingPermission {
permissions[share] = permission
}
}
}
return permissions, nil
}
func (p Permissions) For(share string) Permission {
specific := p[share]
wildcard := p[wildcardShare]
if specific > wildcard {
return specific
}
return wildcard
}