Add support for network service

This commit is contained in:
Daniel
2021-01-19 15:43:22 +01:00
parent 3f8c99517f
commit 12f3c0ea8d
14 changed files with 320 additions and 65 deletions

View File

@@ -21,6 +21,9 @@ const (
// SystemProfileID is the profile ID used for the system/kernel.
SystemProfileID = "_system"
// SystemProfileID is the profile ID used for the Portmaster itself.
PortmasterProfileID = "_portmaster"
)
var getProfileSingleInflight singleflight.Group
@@ -71,6 +74,9 @@ func GetProfile(source profileSource, id, linkedPath string) ( //nolint:gocognit
case SystemProfileID:
profile = New(SourceLocal, SystemProfileID, linkedPath)
err = nil
case PortmasterProfileID:
profile = New(SourceLocal, PortmasterProfileID, linkedPath)
err = nil
}
}
@@ -132,6 +138,76 @@ func GetProfile(source profileSource, id, linkedPath string) ( //nolint:gocognit
return p.(*Profile), nil
}
func GetNetworkHostProfile(remoteIP string) ( //nolint:gocognit
profile *Profile,
err error,
) {
scopedID := makeScopedID(SourceNetwork, remoteIP)
p, err, _ := getProfileSingleInflight.Do(scopedID, func() (interface{}, error) {
var previousVersion *Profile
// Get profile via the scoped ID.
// Check if there already is an active and not outdated profile.
profile = getActiveProfile(scopedID)
if profile != nil {
profile.MarkStillActive()
if profile.outdated.IsSet() {
previousVersion = profile
} else {
return profile, nil
}
}
// Get from database.
profile, err = getProfile(scopedID)
switch {
case err == nil:
// Continue.
case errors.Is(err, database.ErrNotFound):
// Create new profile.
// If there was no profile in the database, create a new one, and return it.
profile = New(SourceNetwork, remoteIP, "")
default:
return nil, err
}
// Process profiles coming directly from the database.
// As we don't use any caching, these will be new objects.
// Mark the profile as being saved internally in order to not trigger an
// update after saving it to the database.
profile.internalSave = true
// Add a layeredProfile to network profiles.
// If we are refetching, assign the layered profile from the previous version.
if previousVersion != nil {
profile.layeredProfile = previousVersion.layeredProfile
}
// Network profiles must have a layered profile, create a new one if it
// does not yet exist.
if profile.layeredProfile == nil {
profile.layeredProfile = NewLayeredProfile(profile)
}
// Add the profile to the currently active profiles.
addActiveProfile(profile)
return profile, nil
})
if err != nil {
return nil, err
}
if p == nil {
return nil, errors.New("profile getter returned nil")
}
return p.(*Profile), nil
}
// getProfile fetches the profile for the given scoped ID.
func getProfile(scopedID string) (profile *Profile, err error) {
// Get profile from the database.

View File

@@ -32,6 +32,7 @@ type profileSource string
const (
SourceLocal profileSource = "local" // local, editable
SourceSpecial profileSource = "special" // specials (read-only)
SourceNetwork profileSource = "network"
SourceCommunity profileSource = "community"
SourceEnterprise profileSource = "enterprise"
)
@@ -386,7 +387,7 @@ func EnsureProfile(r record.Record) (*Profile, error) {
// the profile was changed. If there is data that needs to be fetched from the
// operating system, it will start an async worker to fetch that data and save
// the profile afterwards.
func (profile *Profile) UpdateMetadata(processName string) (changed bool) {
func (profile *Profile) UpdateMetadata(processName, binaryPath string) (changed bool) {
// Check if this is a local profile, else warn and return.
if profile.Source != SourceLocal {
log.Warningf("tried to update metadata for non-local profile %s", profile.ScopedID())
@@ -397,7 +398,7 @@ func (profile *Profile) UpdateMetadata(processName string) (changed bool) {
defer profile.Unlock()
// Check if this is a special profile.
if profile.LinkedPath == "" {
if binaryPath == "" {
// This is a special profile, just assign the processName, if needed, and
// return.
if profile.Name != processName {
@@ -407,6 +408,13 @@ func (profile *Profile) UpdateMetadata(processName string) (changed bool) {
return false
}
// Update LinkedPath if if differs from the process path.
// This will (at the moment) only be the case for the Portmaster profile.
if profile.LinkedPath != binaryPath {
profile.LinkedPath = binaryPath
changed = true
}
var needsUpdateFromSystem bool
// Check profile name.