Streamline configuration
This commit is contained in:
@@ -19,7 +19,7 @@ var (
|
||||
func registerConfigUpdater() error {
|
||||
return module.RegisterEventHook(
|
||||
"config",
|
||||
"config changed",
|
||||
"config change",
|
||||
"update global config profile",
|
||||
updateGlobalConfigProfile,
|
||||
)
|
||||
|
||||
@@ -10,35 +10,41 @@ var (
|
||||
cfgIntOptions = make(map[string]config.IntOption)
|
||||
cfgBoolOptions = make(map[string]config.BoolOption)
|
||||
|
||||
cfgOptionDefaultActionKey = "filter/mode"
|
||||
CfgOptionDefaultActionKey = "filter/defaultAction"
|
||||
cfgOptionDefaultAction config.StringOption
|
||||
|
||||
cfgOptionDisableAutoPermitKey = "filter/disableAutoPermit"
|
||||
CfgOptionDisableAutoPermitKey = "filter/disableAutoPermit"
|
||||
cfgOptionDisableAutoPermit config.IntOption // security level option
|
||||
|
||||
cfgOptionEndpointsKey = "filter/endpoints"
|
||||
CfgOptionEndpointsKey = "filter/endpoints"
|
||||
cfgOptionEndpoints config.StringArrayOption
|
||||
|
||||
cfgOptionServiceEndpointsKey = "filter/serviceEndpoints"
|
||||
CfgOptionServiceEndpointsKey = "filter/serviceEndpoints"
|
||||
cfgOptionServiceEndpoints config.StringArrayOption
|
||||
|
||||
cfgOptionBlockScopeLocalKey = "filter/blockLocal"
|
||||
CfgOptionBlockScopeLocalKey = "filter/blockLocal"
|
||||
cfgOptionBlockScopeLocal config.IntOption // security level option
|
||||
|
||||
cfgOptionBlockScopeLANKey = "filter/blockLAN"
|
||||
CfgOptionBlockScopeLANKey = "filter/blockLAN"
|
||||
cfgOptionBlockScopeLAN config.IntOption // security level option
|
||||
|
||||
cfgOptionBlockScopeInternetKey = "filter/blockInternet"
|
||||
CfgOptionBlockScopeInternetKey = "filter/blockInternet"
|
||||
cfgOptionBlockScopeInternet config.IntOption // security level option
|
||||
|
||||
cfgOptionBlockP2PKey = "filter/blockP2P"
|
||||
CfgOptionBlockP2PKey = "filter/blockP2P"
|
||||
cfgOptionBlockP2P config.IntOption // security level option
|
||||
|
||||
cfgOptionBlockInboundKey = "filter/blockInbound"
|
||||
CfgOptionBlockInboundKey = "filter/blockInbound"
|
||||
cfgOptionBlockInbound config.IntOption // security level option
|
||||
|
||||
cfgOptionEnforceSPNKey = "filter/enforceSPN"
|
||||
CfgOptionEnforceSPNKey = "filter/enforceSPN"
|
||||
cfgOptionEnforceSPN config.IntOption // security level option
|
||||
|
||||
CfgOptionRemoveOutOfScopeDNSKey = "filter/removeOutOfScopeDNS"
|
||||
cfgOptionRemoveOutOfScopeDNS config.IntOption // security level option
|
||||
|
||||
CfgOptionRemoveBlockedDNSKey = "filter/removeBlockedDNS"
|
||||
cfgOptionRemoveBlockedDNS config.IntOption // security level option
|
||||
)
|
||||
|
||||
func registerConfiguration() error {
|
||||
@@ -48,7 +54,7 @@ func registerConfiguration() error {
|
||||
// block - whitelist mode: everything is blocked unless permitted
|
||||
err := config.Register(&config.Option{
|
||||
Name: "Default Filter Action",
|
||||
Key: cfgOptionDefaultActionKey,
|
||||
Key: CfgOptionDefaultActionKey,
|
||||
Description: `The default filter action when nothing else permits or blocks a connection.`,
|
||||
OptType: config.OptTypeString,
|
||||
DefaultValue: "permit",
|
||||
@@ -57,13 +63,13 @@ func registerConfiguration() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgOptionDefaultAction = config.Concurrent.GetAsString(cfgOptionDefaultActionKey, "permit")
|
||||
cfgStringOptions[cfgOptionDefaultActionKey] = cfgOptionDefaultAction
|
||||
cfgOptionDefaultAction = config.Concurrent.GetAsString(CfgOptionDefaultActionKey, "permit")
|
||||
cfgStringOptions[CfgOptionDefaultActionKey] = cfgOptionDefaultAction
|
||||
|
||||
// Disable Auto Permit
|
||||
err = config.Register(&config.Option{
|
||||
Name: "Disable Auto Permit",
|
||||
Key: cfgOptionDisableAutoPermitKey,
|
||||
Key: CfgOptionDisableAutoPermitKey,
|
||||
Description: "Auto Permit searches for a relation between an app and the destionation of a connection - if there is a correlation, the connection will be permitted. This setting is negated in order to provide a streamlined user experience, where higher settings are better.",
|
||||
OptType: config.OptTypeInt,
|
||||
ExternalOptType: "security level",
|
||||
@@ -73,13 +79,13 @@ func registerConfiguration() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgOptionDisableAutoPermit = config.Concurrent.GetAsInt(cfgOptionDisableAutoPermitKey, 4)
|
||||
cfgIntOptions[cfgOptionDisableAutoPermitKey] = cfgOptionDisableAutoPermit
|
||||
cfgOptionDisableAutoPermit = config.Concurrent.GetAsInt(CfgOptionDisableAutoPermitKey, 4)
|
||||
cfgIntOptions[CfgOptionDisableAutoPermitKey] = cfgOptionDisableAutoPermit
|
||||
|
||||
// Endpoint Filter List
|
||||
err = config.Register(&config.Option{
|
||||
Name: "Endpoint Filter List",
|
||||
Key: cfgOptionEndpointsKey,
|
||||
Key: CfgOptionEndpointsKey,
|
||||
Description: "Filter outgoing connections by matching the destination endpoint. Network Scope restrictions still apply.",
|
||||
Help: `Format:
|
||||
Permission:
|
||||
@@ -101,36 +107,36 @@ Examples:
|
||||
- .example.com
|
||||
+ 192.168.0.1/24`,
|
||||
OptType: config.OptTypeStringArray,
|
||||
DefaultValue: nil,
|
||||
DefaultValue: []string{},
|
||||
ExternalOptType: "endpoint list",
|
||||
ValidationRegex: `^(+|-) [A-z0-9\.:-*/]+( [A-z0-9/]+)?$`,
|
||||
ValidationRegex: `^(\+|\-) [A-z0-9\.:\-*/]+( [A-z0-9/]+)?$`,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgOptionEndpoints = config.Concurrent.GetAsStringArray(cfgOptionEndpointsKey, nil)
|
||||
cfgStringArrayOptions[cfgOptionEndpointsKey] = cfgOptionEndpoints
|
||||
cfgOptionEndpoints = config.Concurrent.GetAsStringArray(CfgOptionEndpointsKey, []string{})
|
||||
cfgStringArrayOptions[CfgOptionEndpointsKey] = cfgOptionEndpoints
|
||||
|
||||
// Service Endpoint Filter List
|
||||
err = config.Register(&config.Option{
|
||||
Name: "Service Endpoint Filter List",
|
||||
Key: cfgOptionServiceEndpointsKey,
|
||||
Key: CfgOptionServiceEndpointsKey,
|
||||
Description: "Filter incoming connections by matching the source endpoint. Network Scope restrictions and the inbound permission still apply. Also not that the implicit default action of this list is to always block.",
|
||||
OptType: config.OptTypeStringArray,
|
||||
DefaultValue: nil,
|
||||
DefaultValue: []string{},
|
||||
ExternalOptType: "endpoint list",
|
||||
ValidationRegex: `^(+|-) [A-z0-9\.:-*/]+( [A-z0-9/]+)?$`,
|
||||
ValidationRegex: `^(\+|\-) [A-z0-9\.:\-*/]+( [A-z0-9/]+)?$`,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgOptionServiceEndpoints = config.Concurrent.GetAsStringArray(cfgOptionServiceEndpointsKey, nil)
|
||||
cfgStringArrayOptions[cfgOptionServiceEndpointsKey] = cfgOptionServiceEndpoints
|
||||
cfgOptionServiceEndpoints = config.Concurrent.GetAsStringArray(CfgOptionServiceEndpointsKey, []string{})
|
||||
cfgStringArrayOptions[CfgOptionServiceEndpointsKey] = cfgOptionServiceEndpoints
|
||||
|
||||
// Block Scope Local
|
||||
err = config.Register(&config.Option{
|
||||
Name: "Block Scope Local",
|
||||
Key: cfgOptionBlockScopeLocalKey,
|
||||
Key: CfgOptionBlockScopeLocalKey,
|
||||
Description: "Block connections to your own device, ie. localhost.",
|
||||
OptType: config.OptTypeInt,
|
||||
ExternalOptType: "security level",
|
||||
@@ -140,13 +146,13 @@ Examples:
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgOptionBlockScopeLocal = config.Concurrent.GetAsInt(cfgOptionBlockScopeLocalKey, 0)
|
||||
cfgIntOptions[cfgOptionBlockScopeLocalKey] = cfgOptionBlockScopeLocal
|
||||
cfgOptionBlockScopeLocal = config.Concurrent.GetAsInt(CfgOptionBlockScopeLocalKey, 0)
|
||||
cfgIntOptions[CfgOptionBlockScopeLocalKey] = cfgOptionBlockScopeLocal
|
||||
|
||||
// Block Scope LAN
|
||||
err = config.Register(&config.Option{
|
||||
Name: "Block Scope LAN",
|
||||
Key: cfgOptionBlockScopeLANKey,
|
||||
Key: CfgOptionBlockScopeLANKey,
|
||||
Description: "Block connections to the Local Area Network.",
|
||||
OptType: config.OptTypeInt,
|
||||
ExternalOptType: "security level",
|
||||
@@ -156,13 +162,13 @@ Examples:
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgOptionBlockScopeLAN = config.Concurrent.GetAsInt(cfgOptionBlockScopeLANKey, 0)
|
||||
cfgIntOptions[cfgOptionBlockScopeLANKey] = cfgOptionBlockScopeLAN
|
||||
cfgOptionBlockScopeLAN = config.Concurrent.GetAsInt(CfgOptionBlockScopeLANKey, 0)
|
||||
cfgIntOptions[CfgOptionBlockScopeLANKey] = cfgOptionBlockScopeLAN
|
||||
|
||||
// Block Scope Internet
|
||||
err = config.Register(&config.Option{
|
||||
Name: "Block Scope Internet",
|
||||
Key: cfgOptionBlockScopeInternetKey,
|
||||
Key: CfgOptionBlockScopeInternetKey,
|
||||
Description: "Block connections to the Internet.",
|
||||
OptType: config.OptTypeInt,
|
||||
ExternalOptType: "security level",
|
||||
@@ -172,13 +178,13 @@ Examples:
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgOptionBlockScopeInternet = config.Concurrent.GetAsInt(cfgOptionBlockScopeInternetKey, 0)
|
||||
cfgIntOptions[cfgOptionBlockScopeInternetKey] = cfgOptionBlockScopeInternet
|
||||
cfgOptionBlockScopeInternet = config.Concurrent.GetAsInt(CfgOptionBlockScopeInternetKey, 0)
|
||||
cfgIntOptions[CfgOptionBlockScopeInternetKey] = cfgOptionBlockScopeInternet
|
||||
|
||||
// Block Peer to Peer Connections
|
||||
err = config.Register(&config.Option{
|
||||
Name: "Block Peer to Peer Connections",
|
||||
Key: cfgOptionBlockP2PKey,
|
||||
Key: CfgOptionBlockP2PKey,
|
||||
Description: "Block peer to peer connections. These are connections that are established directly to an IP address on the Internet without resolving a domain name via DNS first.",
|
||||
OptType: config.OptTypeInt,
|
||||
ExternalOptType: "security level",
|
||||
@@ -188,13 +194,13 @@ Examples:
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgOptionBlockP2P = config.Concurrent.GetAsInt(cfgOptionBlockP2PKey, 7)
|
||||
cfgIntOptions[cfgOptionBlockP2PKey] = cfgOptionBlockP2P
|
||||
cfgOptionBlockP2P = config.Concurrent.GetAsInt(CfgOptionBlockP2PKey, 7)
|
||||
cfgIntOptions[CfgOptionBlockP2PKey] = cfgOptionBlockP2P
|
||||
|
||||
// Block Inbound Connections
|
||||
err = config.Register(&config.Option{
|
||||
Name: "Block Inbound Connections",
|
||||
Key: cfgOptionBlockInboundKey,
|
||||
Key: CfgOptionBlockInboundKey,
|
||||
Description: "Block inbound connections to your device. This will usually only be the case if you are running a network service or are using peer to peer software.",
|
||||
OptType: config.OptTypeInt,
|
||||
ExternalOptType: "security level",
|
||||
@@ -204,13 +210,13 @@ Examples:
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgOptionBlockInbound = config.Concurrent.GetAsInt(cfgOptionBlockInboundKey, 6)
|
||||
cfgIntOptions[cfgOptionBlockInboundKey] = cfgOptionBlockInbound
|
||||
cfgOptionBlockInbound = config.Concurrent.GetAsInt(CfgOptionBlockInboundKey, 6)
|
||||
cfgIntOptions[CfgOptionBlockInboundKey] = cfgOptionBlockInbound
|
||||
|
||||
// Enforce SPN
|
||||
err = config.Register(&config.Option{
|
||||
Name: "Enforce SPN",
|
||||
Key: cfgOptionEnforceSPNKey,
|
||||
Key: CfgOptionEnforceSPNKey,
|
||||
Description: "This setting enforces connections to be routed over the SPN. If this is not possible for any reason, connections will be blocked.",
|
||||
OptType: config.OptTypeInt,
|
||||
ReleaseLevel: config.ReleaseLevelExperimental,
|
||||
@@ -221,8 +227,44 @@ Examples:
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgOptionEnforceSPN = config.Concurrent.GetAsInt(cfgOptionEnforceSPNKey, 0)
|
||||
cfgIntOptions[cfgOptionEnforceSPNKey] = cfgOptionEnforceSPN
|
||||
cfgOptionEnforceSPN = config.Concurrent.GetAsInt(CfgOptionEnforceSPNKey, 0)
|
||||
cfgIntOptions[CfgOptionEnforceSPNKey] = cfgOptionEnforceSPN
|
||||
|
||||
// Filter Out-of-Scope DNS Records
|
||||
err = config.Register(&config.Option{
|
||||
Name: "Filter Out-of-Scope DNS Records",
|
||||
Key: CfgOptionRemoveOutOfScopeDNSKey,
|
||||
Description: "Filter DNS answers that are outside of the scope of the server. A server on the public Internet may not respond with a private LAN address.",
|
||||
OptType: config.OptTypeInt,
|
||||
ExpertiseLevel: config.ExpertiseLevelExpert,
|
||||
ReleaseLevel: config.ReleaseLevelBeta,
|
||||
ExternalOptType: "security level",
|
||||
DefaultValue: 7,
|
||||
ValidationRegex: "^(7|6|4)$",
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgOptionRemoveOutOfScopeDNS = config.Concurrent.GetAsInt(CfgOptionRemoveOutOfScopeDNSKey, 7)
|
||||
cfgIntOptions[CfgOptionRemoveOutOfScopeDNSKey] = cfgOptionEnforceSPN
|
||||
|
||||
// Filter DNS Records that would be blocked
|
||||
err = config.Register(&config.Option{
|
||||
Name: "Filter DNS Records that would be blocked",
|
||||
Key: CfgOptionRemoveBlockedDNSKey,
|
||||
Description: "Pre-filter DNS answers that an application would not be allowed to connect to.",
|
||||
OptType: config.OptTypeInt,
|
||||
ExpertiseLevel: config.ExpertiseLevelExpert,
|
||||
ReleaseLevel: config.ReleaseLevelBeta,
|
||||
ExternalOptType: "security level",
|
||||
DefaultValue: 7,
|
||||
ValidationRegex: "^(7|6|4)$",
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cfgOptionRemoveBlockedDNS = config.Concurrent.GetAsInt(CfgOptionRemoveBlockedDNSKey, 7)
|
||||
cfgIntOptions[CfgOptionRemoveBlockedDNSKey] = cfgOptionEnforceSPN
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
54
profile/find.go
Normal file
54
profile/find.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package profile
|
||||
|
||||
import (
|
||||
"github.com/safing/portbase/database/query"
|
||||
"github.com/safing/portbase/log"
|
||||
)
|
||||
|
||||
func FindOrCreateLocalProfileByPath(fullPath string) (profile *Profile, new bool, err error) {
|
||||
// find local profile
|
||||
it, err := profileDB.Query(
|
||||
query.New(makeProfileKey(SourceLocal, "")).Where(
|
||||
query.Where("LinkedPath", query.SameAs, fullPath),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// get first result
|
||||
r := <-it.Next
|
||||
// cancel immediately
|
||||
it.Cancel()
|
||||
|
||||
// return new if none was found
|
||||
if r == nil {
|
||||
profile = New()
|
||||
profile.LinkedPath = fullPath
|
||||
return profile, true, nil
|
||||
}
|
||||
|
||||
// ensure its a profile
|
||||
profile, err = EnsureProfile(r)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// prepare config
|
||||
err = profile.prepConfig()
|
||||
if err != nil {
|
||||
log.Warningf("profiles: profile %s has (partly) invalid configuration: %s", profile.ID, err)
|
||||
}
|
||||
|
||||
// parse config
|
||||
err = profile.parseConfig()
|
||||
if err != nil {
|
||||
log.Warningf("profiles: profile %s has (partly) invalid configuration: %s", profile.ID, err)
|
||||
}
|
||||
|
||||
// mark active
|
||||
markProfileActive(profile)
|
||||
|
||||
// return parsed profile
|
||||
return profile, false, nil
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package profile
|
||||
|
||||
import (
|
||||
"github.com/safing/portbase/log"
|
||||
|
||||
"github.com/safing/portbase/modules"
|
||||
|
||||
// module dependencies
|
||||
@@ -40,5 +42,10 @@ func start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = updateGlobalConfigProfile(module.Ctx, nil)
|
||||
if err != nil {
|
||||
log.Warningf("profile: error during loading global profile from configuration: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -23,8 +23,9 @@ var (
|
||||
type LayeredProfile struct {
|
||||
lock sync.Mutex
|
||||
|
||||
localProfile *Profile
|
||||
layers []*Profile
|
||||
localProfile *Profile
|
||||
layers []*Profile
|
||||
revisionCounter uint64
|
||||
|
||||
validityFlag *abool.AtomicBool
|
||||
validityFlagLock sync.Mutex
|
||||
@@ -32,13 +33,15 @@ type LayeredProfile struct {
|
||||
|
||||
securityLevel *uint32
|
||||
|
||||
DisableAutoPermit config.BoolOption
|
||||
BlockScopeLocal config.BoolOption
|
||||
BlockScopeLAN config.BoolOption
|
||||
BlockScopeInternet config.BoolOption
|
||||
BlockP2P config.BoolOption
|
||||
BlockInbound config.BoolOption
|
||||
EnforceSPN config.BoolOption
|
||||
DisableAutoPermit config.BoolOption
|
||||
BlockScopeLocal config.BoolOption
|
||||
BlockScopeLAN config.BoolOption
|
||||
BlockScopeInternet config.BoolOption
|
||||
BlockP2P config.BoolOption
|
||||
BlockInbound config.BoolOption
|
||||
EnforceSPN config.BoolOption
|
||||
RemoveOutOfScopeDNS config.BoolOption
|
||||
RemoveBlockedDNS config.BoolOption
|
||||
}
|
||||
|
||||
// NewLayeredProfile returns a new layered profile based on the given local profile.
|
||||
@@ -48,39 +51,48 @@ func NewLayeredProfile(localProfile *Profile) *LayeredProfile {
|
||||
new := &LayeredProfile{
|
||||
localProfile: localProfile,
|
||||
layers: make([]*Profile, 0, len(localProfile.LinkedProfiles)+1),
|
||||
revisionCounter: 0,
|
||||
validityFlag: abool.NewBool(true),
|
||||
globalValidityFlag: config.NewValidityFlag(),
|
||||
securityLevel: &securityLevelVal,
|
||||
}
|
||||
|
||||
new.DisableAutoPermit = new.wrapSecurityLevelOption(
|
||||
cfgOptionDisableAutoPermitKey,
|
||||
CfgOptionDisableAutoPermitKey,
|
||||
cfgOptionDisableAutoPermit,
|
||||
)
|
||||
new.BlockScopeLocal = new.wrapSecurityLevelOption(
|
||||
cfgOptionBlockScopeLocalKey,
|
||||
CfgOptionBlockScopeLocalKey,
|
||||
cfgOptionBlockScopeLocal,
|
||||
)
|
||||
new.BlockScopeLAN = new.wrapSecurityLevelOption(
|
||||
cfgOptionBlockScopeLANKey,
|
||||
CfgOptionBlockScopeLANKey,
|
||||
cfgOptionBlockScopeLAN,
|
||||
)
|
||||
new.BlockScopeInternet = new.wrapSecurityLevelOption(
|
||||
cfgOptionBlockScopeInternetKey,
|
||||
CfgOptionBlockScopeInternetKey,
|
||||
cfgOptionBlockScopeInternet,
|
||||
)
|
||||
new.BlockP2P = new.wrapSecurityLevelOption(
|
||||
cfgOptionBlockP2PKey,
|
||||
CfgOptionBlockP2PKey,
|
||||
cfgOptionBlockP2P,
|
||||
)
|
||||
new.BlockInbound = new.wrapSecurityLevelOption(
|
||||
cfgOptionBlockInboundKey,
|
||||
CfgOptionBlockInboundKey,
|
||||
cfgOptionBlockInbound,
|
||||
)
|
||||
new.EnforceSPN = new.wrapSecurityLevelOption(
|
||||
cfgOptionEnforceSPNKey,
|
||||
CfgOptionEnforceSPNKey,
|
||||
cfgOptionEnforceSPN,
|
||||
)
|
||||
new.RemoveOutOfScopeDNS = new.wrapSecurityLevelOption(
|
||||
CfgOptionRemoveOutOfScopeDNSKey,
|
||||
cfgOptionRemoveOutOfScopeDNS,
|
||||
)
|
||||
new.RemoveBlockedDNS = new.wrapSecurityLevelOption(
|
||||
CfgOptionRemoveBlockedDNSKey,
|
||||
cfgOptionRemoveBlockedDNS,
|
||||
)
|
||||
|
||||
// TODO: load referenced profiles
|
||||
|
||||
@@ -100,9 +112,9 @@ func (lp *LayeredProfile) getValidityFlag() *abool.AtomicBool {
|
||||
}
|
||||
|
||||
// Update checks for updated profiles and replaces any outdated profiles.
|
||||
func (lp *LayeredProfile) Update() {
|
||||
func (lp *LayeredProfile) Update() (revisionCounter uint64) {
|
||||
lp.lock.Lock()
|
||||
defer lp.lock.Lock()
|
||||
defer lp.lock.Unlock()
|
||||
|
||||
var changed bool
|
||||
for i, layer := range lp.layers {
|
||||
@@ -130,8 +142,14 @@ func (lp *LayeredProfile) Update() {
|
||||
// get global config validity flag
|
||||
lp.globalValidityFlag.Refresh()
|
||||
|
||||
// update cached data fields
|
||||
lp.updateCaches()
|
||||
|
||||
// bump revision counter
|
||||
lp.revisionCounter++
|
||||
}
|
||||
|
||||
return lp.revisionCounter
|
||||
}
|
||||
|
||||
func (lp *LayeredProfile) updateCaches() {
|
||||
@@ -156,12 +174,14 @@ func (lp *LayeredProfile) SecurityLevel() uint8 {
|
||||
func (lp *LayeredProfile) DefaultAction() uint8 {
|
||||
for _, layer := range lp.layers {
|
||||
if layer.defaultAction > 0 {
|
||||
log.Tracef("profile: default action by layer = %d", layer.defaultAction)
|
||||
return layer.defaultAction
|
||||
}
|
||||
}
|
||||
|
||||
cfgLock.RLock()
|
||||
defer cfgLock.RUnlock()
|
||||
log.Tracef("profile: default action from global = %d", cfgDefaultAction)
|
||||
return cfgDefaultAction
|
||||
}
|
||||
|
||||
@@ -199,38 +219,15 @@ func (lp *LayeredProfile) MatchServiceEndpoint(entity *intel.Entity) (result end
|
||||
return cfgServiceEndpoints.Match(entity)
|
||||
}
|
||||
|
||||
/*
|
||||
func (lp *LayeredProfile) wrapSecurityLevelOption(configKey string, globalConfig config.IntOption) config.BoolOption {
|
||||
valid := no
|
||||
var activeAtLevels uint8
|
||||
|
||||
return func() bool {
|
||||
if !valid.IsSet() {
|
||||
valid = lp.getValidityFlag()
|
||||
|
||||
found := false
|
||||
layerLoop:
|
||||
for _, layer := range lp.layers {
|
||||
layerLevel, ok := layer.configPerspective.GetAsInt(configKey)
|
||||
if ok {
|
||||
found = true
|
||||
// TODO: add instead?
|
||||
activeAtLevels = uint8(layerLevel)
|
||||
break layerLoop
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
activeAtLevels = uint8(globalConfig())
|
||||
}
|
||||
}
|
||||
|
||||
return activeAtLevels&max(
|
||||
lp.SecurityLevel(), // layered profile security level
|
||||
status.ActiveSecurityLevel(), // global security level
|
||||
) > 0
|
||||
}
|
||||
// AddEndpoint adds an endpoint to the local endpoint list, saves the local profile and reloads the configuration.
|
||||
func (lp *LayeredProfile) AddEndpoint(newEntry string) {
|
||||
lp.localProfile.AddEndpoint(newEntry)
|
||||
}
|
||||
|
||||
// AddServiceEndpoint adds a service endpoint to the local endpoint list, saves the local profile and reloads the configuration.
|
||||
func (lp *LayeredProfile) AddServiceEndpoint(newEntry string) {
|
||||
lp.localProfile.AddServiceEndpoint(newEntry)
|
||||
}
|
||||
*/
|
||||
|
||||
func (lp *LayeredProfile) wrapSecurityLevelOption(configKey string, globalConfig config.IntOption) config.BoolOption {
|
||||
activeAtLevels := lp.wrapIntOption(configKey, globalConfig)
|
||||
|
||||
@@ -90,18 +90,13 @@ type Profile struct { //nolint:maligned // not worth the effort
|
||||
}
|
||||
|
||||
func (profile *Profile) prepConfig() (err error) {
|
||||
profile.Lock()
|
||||
defer profile.Unlock()
|
||||
|
||||
// prepare configuration
|
||||
profile.configPerspective, err = config.NewPerspective(profile.Config)
|
||||
profile.oudated = abool.New()
|
||||
return
|
||||
}
|
||||
|
||||
func (profile *Profile) parseConfig() error {
|
||||
profile.Lock()
|
||||
defer profile.Unlock()
|
||||
|
||||
if profile.configPerspective == nil {
|
||||
return errors.New("config not prepared")
|
||||
}
|
||||
@@ -115,7 +110,7 @@ func (profile *Profile) parseConfig() error {
|
||||
var err error
|
||||
var lastErr error
|
||||
|
||||
action, ok := profile.configPerspective.GetAsString(cfgOptionDefaultActionKey)
|
||||
action, ok := profile.configPerspective.GetAsString(CfgOptionBlockInboundKey)
|
||||
if ok {
|
||||
switch action {
|
||||
case "permit":
|
||||
@@ -129,7 +124,7 @@ func (profile *Profile) parseConfig() error {
|
||||
}
|
||||
}
|
||||
|
||||
list, ok := profile.configPerspective.GetAsStringArray(cfgOptionEndpointsKey)
|
||||
list, ok := profile.configPerspective.GetAsStringArray(CfgOptionEndpointsKey)
|
||||
if ok {
|
||||
profile.endpoints, err = endpoints.ParseEndpoints(list)
|
||||
if err != nil {
|
||||
@@ -137,7 +132,7 @@ func (profile *Profile) parseConfig() error {
|
||||
}
|
||||
}
|
||||
|
||||
list, ok = profile.configPerspective.GetAsStringArray(cfgOptionServiceEndpointsKey)
|
||||
list, ok = profile.configPerspective.GetAsStringArray(CfgOptionServiceEndpointsKey)
|
||||
if ok {
|
||||
profile.serviceEndpoints, err = endpoints.ParseEndpoints(list)
|
||||
if err != nil {
|
||||
@@ -150,11 +145,18 @@ func (profile *Profile) parseConfig() error {
|
||||
|
||||
// New returns a new Profile.
|
||||
func New() *Profile {
|
||||
return &Profile{
|
||||
profile := &Profile{
|
||||
ID: uuid.NewV4().String(),
|
||||
Source: SourceLocal,
|
||||
Created: time.Now().Unix(),
|
||||
Config: make(map[string]interface{}),
|
||||
}
|
||||
|
||||
// create placeholders
|
||||
_ = profile.prepConfig()
|
||||
_ = profile.parseConfig()
|
||||
|
||||
return profile
|
||||
}
|
||||
|
||||
// ScopedID returns the scoped ID (Source + ID) of the profile.
|
||||
@@ -192,6 +194,41 @@ func (profile *Profile) String() string {
|
||||
return profile.Name
|
||||
}
|
||||
|
||||
// AddEndpoint adds an endpoint to the endpoint list, saves the profile and reloads the configuration.
|
||||
func (profile *Profile) AddEndpoint(newEntry string) {
|
||||
profile.addEndpointyEntry(CfgOptionEndpointsKey, newEntry)
|
||||
}
|
||||
|
||||
// AddServiceEndpoint adds a service endpoint to the endpoint list, saves the profile and reloads the configuration.
|
||||
func (profile *Profile) AddServiceEndpoint(newEntry string) {
|
||||
profile.addEndpointyEntry(CfgOptionServiceEndpointsKey, newEntry)
|
||||
}
|
||||
|
||||
func (profile *Profile) addEndpointyEntry(cfgKey, newEntry string) {
|
||||
profile.Lock()
|
||||
// get, update, save endpoints list
|
||||
endpointList, ok := profile.configPerspective.GetAsStringArray(cfgKey)
|
||||
if !ok {
|
||||
endpointList = make([]string, 0, 1)
|
||||
}
|
||||
endpointList = append(endpointList, newEntry)
|
||||
profile.Config[cfgKey] = endpointList
|
||||
|
||||
// save without full reload
|
||||
profile.internalSave = true
|
||||
profile.Unlock()
|
||||
err := profile.Save()
|
||||
if err != nil {
|
||||
log.Warningf("profile: failed to save profile after adding endpoint: %s", err)
|
||||
}
|
||||
|
||||
// reload manually
|
||||
err = profile.parseConfig()
|
||||
if err != nil {
|
||||
log.Warningf("profile: failed to parse profile config after adding endpoint: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetProfile loads a profile from the database.
|
||||
func GetProfile(source, id string) (*Profile, error) {
|
||||
return GetProfileByScopedID(makeScopedID(source, id))
|
||||
@@ -217,6 +254,10 @@ func GetProfileByScopedID(scopedID string) (*Profile, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// lock for prepping
|
||||
profile.Lock()
|
||||
defer profile.Unlock()
|
||||
|
||||
// prepare config
|
||||
err = profile.prepConfig()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user