Fix layered profiles not readable via the API

This commit is contained in:
Patrick Pacher 2020-10-30 16:43:49 +01:00
parent c0509042a0
commit fb6b34ebe5
4 changed files with 75 additions and 30 deletions

View file

@ -16,18 +16,26 @@ var (
activeProfilesLock sync.RWMutex activeProfilesLock sync.RWMutex
) )
// getActiveProfile returns a cached copy of an active profile and nil if it isn't found. // getActiveProfile returns a cached copy of an active profile and
// nil if it isn't found.
func getActiveProfile(scopedID string) *Profile { func getActiveProfile(scopedID string) *Profile {
activeProfilesLock.RLock() activeProfilesLock.RLock()
defer activeProfilesLock.RUnlock() defer activeProfilesLock.RUnlock()
activeProfile, ok := activeProfiles[scopedID] return activeProfiles[scopedID]
if ok { }
activeProfile.MarkStillActive()
return activeProfile // getAllActiveProfiles returns a slice of active profiles.
func getAllActiveProfiles() []*Profile {
activeProfilesLock.RLock()
defer activeProfilesLock.RUnlock()
result := make([]*Profile, 0, len(activeProfiles))
for _, p := range activeProfiles {
result = append(result, p)
} }
return nil return result
} }
// findActiveProfile searched for an active local profile using the linked path. // findActiveProfile searched for an active local profile using the linked path.

View file

@ -51,6 +51,8 @@ func GetProfile(source profileSource, id, linkedPath string) ( //nolint:gocognit
// Check if there already is an active and not outdated profile. // Check if there already is an active and not outdated profile.
profile = getActiveProfile(scopedID) profile = getActiveProfile(scopedID)
if profile != nil { if profile != nil {
profile.MarkStillActive()
if profile.outdated.IsSet() { if profile.outdated.IsSet() {
previousVersion = profile previousVersion = profile
} else { } else {

View file

@ -5,11 +5,12 @@ import (
"strings" "strings"
"github.com/safing/portbase/database/record" "github.com/safing/portbase/database/record"
"github.com/safing/portbase/log"
"github.com/safing/portbase/runtime" "github.com/safing/portbase/runtime"
) )
const ( const (
revisionProviderPrefix = "runtime:layeredProfile/" revisionProviderPrefix = "layeredProfile/"
) )
var ( var (
@ -18,24 +19,50 @@ var (
) )
func registerRevisionProvider() error { func registerRevisionProvider() error {
_, err := runtime.DefaultRegistry.Register( _, err := runtime.Register(
revisionProviderPrefix, revisionProviderPrefix,
runtime.SimpleValueGetterFunc(getRevision), runtime.SimpleValueGetterFunc(getRevisions),
) )
return err return err
} }
func getRevision(key string) ([]record.Record, error) { func getRevisions(key string) ([]record.Record, error) {
log.Warningf("loading for key " + key)
key = strings.TrimPrefix(key, revisionProviderPrefix) key = strings.TrimPrefix(key, revisionProviderPrefix)
// Get active profile. var profiles []*Profile
profile := getActiveProfile(key)
if profile == nil { if key == "" {
return nil, errProfileNotActive profiles = getAllActiveProfiles()
} else {
// Get active profile.
profile := getActiveProfile(key)
if profile == nil {
return nil, errProfileNotActive
}
} }
records := make([]record.Record, 0, len(profiles))
for _, p := range profiles {
layered, err := getProfileRevision(p)
if err != nil {
log.Warningf("failed to get layered profile for %s: %s", p.ID, err)
continue
}
records = append(records, layered)
}
return records, nil
}
// getProfileRevision returns the layered profile for p.
// It also updates the layered profile if required.
func getProfileRevision(p *Profile) (*LayeredProfile, error) {
// Get layered profile. // Get layered profile.
layeredProfile := profile.LayeredProfile() layeredProfile := p.LayeredProfile()
if layeredProfile == nil { if layeredProfile == nil {
return nil, errNoLayeredProfile return nil, errNoLayeredProfile
} }
@ -45,5 +72,5 @@ func getRevision(key string) ([]record.Record, error) {
layeredProfile.Update() layeredProfile.Update()
} }
return []record.Record{layeredProfile}, nil return layeredProfile, nil
} }

View file

@ -7,6 +7,7 @@ import (
"github.com/safing/portbase/database/record" "github.com/safing/portbase/database/record"
"github.com/safing/portbase/log" "github.com/safing/portbase/log"
"github.com/safing/portbase/runtime"
"github.com/safing/portmaster/status" "github.com/safing/portmaster/status"
@ -31,19 +32,24 @@ type LayeredProfile struct {
// These functions give layered access to configuration options and require // These functions give layered access to configuration options and require
// the layered profile to be read locked. // the layered profile to be read locked.
DisableAutoPermit config.BoolOption
BlockScopeLocal config.BoolOption // TODO(ppacher): we need JSON tags here so the layeredProfile can be exposed
BlockScopeLAN config.BoolOption // via the API. If we ever switch away from JSON to something else supported
BlockScopeInternet config.BoolOption // by DSD this WILL BREAK!
BlockP2P config.BoolOption
BlockInbound config.BoolOption DisableAutoPermit config.BoolOption `json:"-"`
RemoveOutOfScopeDNS config.BoolOption BlockScopeLocal config.BoolOption `json:"-"`
RemoveBlockedDNS config.BoolOption BlockScopeLAN config.BoolOption `json:"-"`
FilterSubDomains config.BoolOption BlockScopeInternet config.BoolOption `json:"-"`
FilterCNAMEs config.BoolOption BlockP2P config.BoolOption `json:"-"`
PreventBypassing config.BoolOption BlockInbound config.BoolOption `json:"-"`
DomainHeuristics config.BoolOption RemoveOutOfScopeDNS config.BoolOption `json:"-"`
UseSPN config.BoolOption RemoveBlockedDNS config.BoolOption `json:"-"`
FilterSubDomains config.BoolOption `json:"-"`
FilterCNAMEs config.BoolOption `json:"-"`
PreventBypassing config.BoolOption `json:"-"`
DomainHeuristics config.BoolOption `json:"-"`
UseSPN config.BoolOption `json:"-"`
} }
// NewLayeredProfile returns a new layered profile based on the given local profile. // NewLayeredProfile returns a new layered profile based on the given local profile.
@ -118,7 +124,9 @@ func NewLayeredProfile(localProfile *Profile) *LayeredProfile {
new.updateCaches() new.updateCaches()
new.SetKey(revisionProviderPrefix + localProfile.ID) new.CreateMeta()
new.SetKey(runtime.DefaultRegistry.DatabaseName() + ":" + revisionProviderPrefix + localProfile.ID)
return new return new
} }