updated config tests; updated rpki config
This commit is contained in:
parent
ad8a55815c
commit
fd0700ed6f
@ -126,11 +126,11 @@ type RejectCandidatesConfig struct {
|
||||
// validation state.
|
||||
type RpkiConfig struct {
|
||||
// Define communities
|
||||
Enabled bool `ini:"enabled"`
|
||||
Valid []string `ini:"valid"`
|
||||
Unknown []string `ini:"unknown"`
|
||||
NotChecked []string `ini:"not_checked"`
|
||||
Invalid []string `ini:"invalid"`
|
||||
Enabled bool `ini:"enabled"`
|
||||
Valid [][]string `ini:"valid"`
|
||||
Unknown [][]string `ini:"unknown"`
|
||||
NotChecked [][]string `ini:"not_checked"`
|
||||
Invalid [][]string `ini:"invalid"`
|
||||
}
|
||||
|
||||
// UIConfig holds runtime settings for the web client
|
||||
@ -486,70 +486,68 @@ func getRpkiConfig(config *ini.File) (RpkiConfig, error) {
|
||||
// Defaults taken from:
|
||||
// https://www.euro-ix.net/en/forixps/large-bgp-communities/
|
||||
section := config.Section("rpki")
|
||||
lines := strings.Split(section.Body(), "\n")
|
||||
|
||||
for _, line := range lines {
|
||||
l := strings.TrimSpace(line)
|
||||
if !strings.Contains(l, "=") {
|
||||
continue
|
||||
}
|
||||
parts := strings.SplitN(l, "=", 2)
|
||||
if len(parts) != 2 {
|
||||
return rpki, fmt.Errorf("invalid rpki config line: %s", line)
|
||||
}
|
||||
key := strings.TrimSpace(parts[0])
|
||||
value := strings.Split(strings.TrimSpace(parts[1]), ":")
|
||||
|
||||
if key == "enabled" {
|
||||
rpki.Enabled = parts[1] == "true"
|
||||
} else if key == "valid" {
|
||||
rpki.Valid = append(rpki.Valid, value)
|
||||
} else if key == "not_checked" {
|
||||
rpki.NotChecked = append(rpki.NotChecked, value)
|
||||
} else if key == "invalid" {
|
||||
rpki.Invalid = append(rpki.Invalid, value)
|
||||
} else if key == "unknown" {
|
||||
rpki.Unknown = append(rpki.Unknown, value)
|
||||
} else {
|
||||
return rpki, fmt.Errorf("invalid rpki config line: %s", line)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if err := section.MapTo(&rpki); err != nil {
|
||||
return rpki, err
|
||||
}
|
||||
|
||||
fallbackAsn, err := getOwnASN(config)
|
||||
if err != nil {
|
||||
log.Println(
|
||||
"Own ASN is not configured.",
|
||||
"This might lead to unexpected behaviour with BGP large communities",
|
||||
)
|
||||
}
|
||||
ownAsn := fmt.Sprintf("%d", fallbackAsn)
|
||||
|
||||
// Fill in defaults or postprocess config value
|
||||
if len(rpki.Valid) == 0 {
|
||||
rpki.Valid = []string{ownAsn, "1000", "1"}
|
||||
} else {
|
||||
rpki.Valid = strings.SplitN(rpki.Valid[0], ":", 3)
|
||||
rpki.Valid = [][]string{{"*", "1000", "1"}}
|
||||
}
|
||||
|
||||
if len(rpki.Unknown) == 0 {
|
||||
rpki.Unknown = []string{ownAsn, "1000", "2"}
|
||||
} else {
|
||||
rpki.Unknown = strings.SplitN(rpki.Unknown[0], ":", 3)
|
||||
rpki.Unknown = [][]string{{"*", "1000", "2"}}
|
||||
}
|
||||
|
||||
if len(rpki.NotChecked) == 0 {
|
||||
rpki.NotChecked = []string{ownAsn, "1000", "3"}
|
||||
} else {
|
||||
rpki.NotChecked = strings.SplitN(rpki.NotChecked[0], ":", 3)
|
||||
rpki.NotChecked = [][]string{{"*", "1000", "3"}}
|
||||
}
|
||||
|
||||
// As the euro-ix document states, this can be a range.
|
||||
if len(rpki.Invalid) == 0 {
|
||||
rpki.Invalid = []string{ownAsn, "1000", "4", "*"}
|
||||
} else {
|
||||
// Preprocess
|
||||
rpki.Invalid = strings.SplitN(rpki.Invalid[0], ":", 3)
|
||||
if len(rpki.Invalid) != 3 {
|
||||
// This is wrong, we should have three parts (RS):1000:[range]
|
||||
return rpki, fmt.Errorf(
|
||||
"unexpected rpki.Invalid configuration: %v", rpki.Invalid)
|
||||
for i, com := range rpki.Invalid {
|
||||
if len(com) != 3 {
|
||||
return rpki, fmt.Errorf("Invalid RPKI invalid config: %v", com)
|
||||
}
|
||||
tokens := strings.Split(rpki.Invalid[2], "-")
|
||||
rpki.Invalid = append([]string{rpki.Invalid[0], rpki.Invalid[1]}, tokens...)
|
||||
tokens := strings.Split(com[2], "-")
|
||||
rpki.Invalid[i] = append([]string{com[0], com[1]}, tokens...)
|
||||
}
|
||||
if len(rpki.Invalid) == 0 {
|
||||
rpki.Invalid = [][]string{{"*", "1000", "4", "*"}}
|
||||
}
|
||||
|
||||
return rpki, nil
|
||||
}
|
||||
|
||||
// Helper: Get own ASN from ini
|
||||
// This is now easy, since we enforce an ASN in
|
||||
// the [server] section.
|
||||
func getOwnASN(config *ini.File) (int, error) {
|
||||
server := config.Section("server")
|
||||
asn := server.Key("asn").MustInt(-1)
|
||||
|
||||
if asn == -1 {
|
||||
return 0, fmt.Errorf("could not get own ASN from config")
|
||||
}
|
||||
|
||||
return asn, nil
|
||||
}
|
||||
|
||||
// Get UI config: Theme settings
|
||||
func getThemeConfig(config *ini.File) ThemeConfig {
|
||||
baseConfig := config.Section("theme")
|
||||
@ -823,18 +821,35 @@ func getSources(config *ini.File) ([]*SourceConfig, error) {
|
||||
return sources, nil
|
||||
}
|
||||
|
||||
// preprocessConfig parses the variables section of the config
|
||||
// preprocessConfig parses the variables in the config
|
||||
// and applies it to the rest of the config.
|
||||
func preprocessConfig(data []byte) []byte {
|
||||
lines := bytes.Split(data, []byte("\n"))
|
||||
config := make([][]byte, 0, len(lines))
|
||||
|
||||
expMap := ExpandMap{}
|
||||
for _, line := range lines {
|
||||
|
||||
l := strings.TrimSpace(string(line))
|
||||
if strings.HasPrefix(l, "$") {
|
||||
expMap.AddExpr(l[1:])
|
||||
continue
|
||||
}
|
||||
config = append(config, line)
|
||||
}
|
||||
|
||||
return bytes.Join(config, []byte("\n"))
|
||||
// Now apply to config
|
||||
configLines := []string{}
|
||||
for _, line := range config {
|
||||
l := string(line)
|
||||
exp, err := expMap.Expand(l)
|
||||
if err != nil {
|
||||
log.Fatal("Error expanding expression in config:", l, err)
|
||||
}
|
||||
for _, e := range exp {
|
||||
configLines = append(configLines, e)
|
||||
}
|
||||
}
|
||||
return []byte(strings.Join(configLines, "\n"))
|
||||
}
|
||||
|
||||
// LoadConfig reads a configuration from a file.
|
||||
@ -860,6 +875,7 @@ func LoadConfig(file string) (*Config, error) {
|
||||
"blackhole_communities",
|
||||
"rejection_reasons",
|
||||
"noexport_reasons",
|
||||
"rpki",
|
||||
},
|
||||
}, configData)
|
||||
if err != nil {
|
||||
|
@ -167,32 +167,21 @@ func TestBlackholeParsing(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOwnASN(t *testing.T) {
|
||||
config, err := LoadConfig("testdata/alice.conf")
|
||||
if err != nil {
|
||||
t.Fatal("Could not load test config:", err)
|
||||
}
|
||||
|
||||
if config.Server.Asn != 9033 {
|
||||
t.Error("Expected a set server asn")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRpkiConfig(t *testing.T) {
|
||||
config, err := LoadConfig("testdata/alice.conf")
|
||||
if err != nil {
|
||||
t.Fatal("Could not load test config:", err)
|
||||
}
|
||||
|
||||
if len(config.UI.Rpki.Valid) != 3 {
|
||||
if len(config.UI.Rpki.Valid[0]) != 3 {
|
||||
t.Error("Unexpected RPKI:VALID,", config.UI.Rpki.Valid)
|
||||
}
|
||||
if len(config.UI.Rpki.Invalid) != 4 {
|
||||
if len(config.UI.Rpki.Invalid[0]) != 4 {
|
||||
t.Fatal("Unexpected RPKI:INVALID,", config.UI.Rpki.Invalid)
|
||||
}
|
||||
|
||||
// Check fallback
|
||||
if config.UI.Rpki.NotChecked[0] != "9033" {
|
||||
if config.UI.Rpki.NotChecked[0][0] != "*" {
|
||||
t.Error(
|
||||
"Expected NotChecked to fall back to defaults, got:",
|
||||
config.UI.Rpki.NotChecked,
|
||||
@ -200,7 +189,7 @@ func TestRpkiConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
// Check range postprocessing
|
||||
if config.UI.Rpki.Invalid[3] != "*" {
|
||||
if config.UI.Rpki.Invalid[0][3] != "*" {
|
||||
t.Error("Missing wildcard from config")
|
||||
}
|
||||
|
||||
|
@ -119,5 +119,4 @@ func TestExpandBgpCommunities(t *testing.T) {
|
||||
t.Errorf("Expected %d results, got %d", expected, len(exp))
|
||||
}
|
||||
t.Log(exp)
|
||||
|
||||
}
|
||||
|
50
pkg/config/testdata/alice.conf
vendored
50
pkg/config/testdata/alice.conf
vendored
@ -2,6 +2,13 @@
|
||||
# Alice-LG configuration example
|
||||
# ======================================
|
||||
|
||||
$ASN01 = 1111
|
||||
$ASN02 = 2222
|
||||
|
||||
$SW1001 = switch01.dc01
|
||||
$SW1002 = switch02.dc01
|
||||
$SW2023 = switch23.dc02
|
||||
|
||||
[server]
|
||||
# configures the built-in webserver and provides global application settings
|
||||
listen_http = 127.0.0.1:7340
|
||||
@ -9,7 +16,6 @@ listen_http = 127.0.0.1:7340
|
||||
enable_prefix_lookup = true
|
||||
# Try to refresh the neighbor status on every request to /neighbors
|
||||
enable_neighbors_status_refresh = false
|
||||
asn = 9033
|
||||
# this ASN is used as a fallback value in the RPKI feature and for route
|
||||
# filtering evaluation with large BGP communities
|
||||
|
||||
@ -55,16 +61,16 @@ routes_not_exported_page_size = 250
|
||||
[rejection_reasons]
|
||||
# a pair of a large BGP community value and a string to signal the processing
|
||||
# results of route filtering
|
||||
9033:65666:1 = An IP Bogon was detected
|
||||
9033:65666:2 = Prefix is longer than 64
|
||||
9033:65666:3 = Prefix is longer than 24
|
||||
9033:65666:4 = AS path contains a bogon AS
|
||||
9033:65666:5 = AS path length is longer than 64
|
||||
9033:65666:6 = First AS in path is not the same as the Peer AS
|
||||
9033:65666:7 = ECIX prefix hijack
|
||||
9033:65666:8 = Origin AS not found in IRRDB for Peer AS-SET
|
||||
9033:65666:9 = Prefix not found in IRRDB for Origin AS
|
||||
9033:65666:10 = Advertised nexthop address is not the same as the peer
|
||||
{{ASN*}}:65666:1 = An IP Bogon was detected
|
||||
{{ASN*}}:65666:2 = Prefix is longer than 64
|
||||
{{ASN*}}:65666:3 = Prefix is longer than 24
|
||||
{{ASN*}}:65666:4 = AS path contains a bogon AS
|
||||
{{ASN*}}:65666:5 = AS path length is longer than 64
|
||||
{{ASN*}}:65666:6 = First AS in path is not the same as the Peer AS
|
||||
{{ASN*}}:65666:7 = ECIX prefix hijack
|
||||
{{ASN*}}:65666:8 = Origin AS not found in IRRDB for Peer AS-SET
|
||||
{{ASN*}}:65666:9 = Prefix not found in IRRDB for Origin AS
|
||||
{{ASN*}}:65666:10 = Advertised nexthop address is not the same as the peer
|
||||
|
||||
23:42:1 = Some made up reason
|
||||
|
||||
@ -80,13 +86,13 @@ load_on_demand = true # Default: false
|
||||
[noexport_reasons]
|
||||
# a pair of a large BGP community value and a string to signal the processing
|
||||
# results of route distribution and the distribution policy applied to a route
|
||||
9033:65667:1 = The target peer policy is Fairly-open and the sender ASN is an exception
|
||||
9033:65667:2 = The target peer policy is Selective and the sender ASN is no exception
|
||||
9033:65667:3 = The target peer policy is set to restrictive
|
||||
9033:65667:4 = The sender has specifically refused export to the target peer, either through sending 65000:AS, or through the portal
|
||||
9033:65667:5 = The sender has refused export to all peers and the target is no exception, either through sending 65000:0, or through the portal
|
||||
9033:65667:6 = The Sender has set (peerRTTHigherDeny:ms) and the targets RTT ms >= then the ms in the community
|
||||
9033:65667:7 = The Sender has set (peerRTTLowerDeny:ms) and the targets RTT ms <= then the ms in the community
|
||||
{{ASN*}}:65667:1 = The target peer policy is Fairly-open and the sender ASN is an exception
|
||||
{{ASN*}}:65667:2 = The target peer policy is Selective and the sender ASN is no exception
|
||||
{{ASN*}}:65667:3 = The target peer policy is set to restrictive
|
||||
{{ASN*}}:65667:4 = The sender has specifically refused export to the target peer, either through sending 65000:AS, or through the portal
|
||||
{{ASN*}}:65667:5 = The sender has refused export to all peers and the target is no exception, either through sending 65000:0, or through the portal
|
||||
{{ASN*}}:65667:6 = The Sender has set (peerRTTHigherDeny:ms) and the targets RTT ms >= then the ms in the community
|
||||
{{ASN*}}:65667:7 = The Sender has set (peerRTTLowerDeny:ms) and the targets RTT ms <= then the ms in the community
|
||||
|
||||
23:46:1 = Some other made up reason
|
||||
|
||||
@ -102,10 +108,10 @@ enabled = true
|
||||
|
||||
# Optional, falling back to defaults as defined in:
|
||||
# https://www.euro-ix.net/en/forixps/large-bgp-communities/
|
||||
valid = 23042:1000:1
|
||||
unknown = 23042:1000:2
|
||||
valid = {{ASN*}}:1000:1
|
||||
unknown = {{ASN*}}:1000:2
|
||||
# not_checked = 23042:1000:3
|
||||
invalid = 23042:1000:4-*
|
||||
invalid = {{ASN*}}:1000:4-*
|
||||
|
||||
|
||||
# Define other known bgp communities
|
||||
@ -115,6 +121,8 @@ invalid = 23042:1000:4-*
|
||||
# Wildcards are supported aswell:
|
||||
0:* = do not redistribute to AS$1
|
||||
|
||||
{{ASN*}}:911:{SW*} = Redistribute to {{SW*}}
|
||||
|
||||
#
|
||||
# Define columns for neighbours and routes table,
|
||||
# with <key> = <Table Header>
|
||||
|
Loading…
x
Reference in New Issue
Block a user