TUN-7463: Add default ingress rule if no ingress rules are provided when updating the configuration

This commit is contained in:
João "Pisco" Fernandes
2023-06-09 18:17:04 +01:00
parent 58b27a1ccf
commit 925ec100d6
4 changed files with 63 additions and 27 deletions

View File

@@ -28,8 +28,8 @@ type Orchestrator struct {
lock sync.RWMutex
// Underlying value is proxy.Proxy, can be read without the lock, but still needs the lock to update
proxy atomic.Value
// Set of local ingress rules defined at cloudflared startup (separate from user-defined ingress rules)
localRules []ingress.Rule
// Set of internal ingress rules defined at cloudflared startup (separate from user-defined ingress rules)
internalRules []ingress.Rule
warpRoutingEnabled atomic.Bool
config *Config
tags []tunnelpogs.Tag
@@ -41,13 +41,13 @@ type Orchestrator struct {
proxyShutdownC chan<- struct{}
}
func NewOrchestrator(ctx context.Context, config *Config, tags []tunnelpogs.Tag, localRules []ingress.Rule, log *zerolog.Logger) (*Orchestrator, error) {
func NewOrchestrator(ctx context.Context, config *Config, tags []tunnelpogs.Tag, internalRules []ingress.Rule, log *zerolog.Logger) (*Orchestrator, error) {
o := &Orchestrator{
// Lowest possible version, any remote configuration will have version higher than this
// Starting at -1 allows a configuration migration (local to remote) to override the current configuration as it
// will start at version 0.
currentVersion: -1,
localRules: localRules,
internalRules: internalRules,
config: config,
tags: tags,
log: log,
@@ -116,8 +116,13 @@ func (o *Orchestrator) updateIngress(ingressRules ingress.Ingress, warpRouting i
default:
}
// Assign the local ingress rules to the parsed ingress
ingressRules.LocalRules = o.localRules
// Assign the internal ingress rules to the parsed ingress
ingressRules.InternalRules = o.internalRules
// Check if ingress rules are empty, and add the default route if so.
if ingressRules.IsEmpty() {
ingressRules.Rules = ingress.GetDefaultIngressRules(o.log)
}
// Start new proxy before closing the ones from last version.
// The upside is we don't need to restart proxy from last version, which can fail

View File

@@ -91,15 +91,15 @@ func TestUpdateConfiguration(t *testing.T) {
"enabled": true,
"connectTimeout": 10
}
}
}
`)
updateWithValidation(t, orchestrator, 2, configJSONV2)
configV2 := orchestrator.config
// Validate local ingress rules
require.Equal(t, "management.argotunnel.com", configV2.Ingress.LocalRules[0].Hostname)
require.True(t, configV2.Ingress.LocalRules[0].Matches("management.argotunnel.com", "/ping"))
require.Equal(t, "management", configV2.Ingress.LocalRules[0].Service.String())
// Validate internal ingress rules
require.Equal(t, "management.argotunnel.com", configV2.Ingress.InternalRules[0].Hostname)
require.True(t, configV2.Ingress.InternalRules[0].Matches("management.argotunnel.com", "/ping"))
require.Equal(t, "management", configV2.Ingress.InternalRules[0].Service.String())
// Validate ingress rule 0
require.Equal(t, "jira.tunnel.org", configV2.Ingress.Rules[0].Hostname)
require.True(t, configV2.Ingress.Rules[0].Matches("jira.tunnel.org", "/login"))
@@ -145,7 +145,7 @@ func TestUpdateConfiguration(t *testing.T) {
{
"originRequest":
}
`)
resp = orchestrator.UpdateConfig(3, invalidJSON)
@@ -165,7 +165,7 @@ func TestUpdateConfiguration(t *testing.T) {
"warp-routing": {
"enabled": false
}
}
}
`)
updateWithValidation(t, orchestrator, 10, configJSONV10)
configV10 := orchestrator.config
@@ -204,12 +204,34 @@ func TestUpdateConfiguration_FromMigration(t *testing.T) {
"warp-routing": {
"enabled": true
}
}
}
`)
updateWithValidation(t, orchestrator, 0, configJSONV2)
require.Len(t, orchestrator.config.Ingress.Rules, 1)
}
// Validates that the default ingress rule will be set if there is no rule provided from the remote.
func TestUpdateConfiguration_WithoutIngressRule(t *testing.T) {
initConfig := &Config{
Ingress: &ingress.Ingress{},
}
orchestrator, err := NewOrchestrator(context.Background(), initConfig, testTags, []ingress.Rule{}, &testLogger)
require.NoError(t, err)
initOriginProxy, err := orchestrator.GetOriginProxy()
require.NoError(t, err)
require.Implements(t, (*connection.OriginProxy)(nil), initOriginProxy)
// We need to create an empty RemoteConfigJSON because that will get unmarshalled to a RemoteConfig
emptyConfig := &ingress.RemoteConfigJSON{}
configBytes, err := json.Marshal(emptyConfig)
if err != nil {
require.FailNow(t, "The RemoteConfigJSON shouldn't fail while being marshalled")
}
updateWithValidation(t, orchestrator, 0, configBytes)
require.Len(t, orchestrator.config.Ingress.Rules, 1)
}
// TestConcurrentUpdateAndRead makes sure orchestrator can receive updates and return origin proxy concurrently
func TestConcurrentUpdateAndRead(t *testing.T) {
const (