CubeEgress Architecture for Domain Allowlisting and Credential Injection

CubeEgress implements a first-match-wins L7 egress firewall that filters traffic via domain allowlisting and injects credentials through HTTP header manipulation before forwarding requests.

CubeEgress is the Layer 7 egress firewall integrated into the TencentCloud CubeSandbox network stack. Its architecture enables secure outbound communication by combining domain-based access control with dynamic credential injection. Understanding the internal data model and policy propagation flow is essential for operators configuring egress rules in production environments.

Core Components of the CubeEgress Architecture

The CubeEgress engine is built around four interconnected data structures defined in network-agent/internal/service/types.go.

EgressRule – The Policy Container

The EgressRule struct (line 130) serves as the user-facing rule object that expresses what to allow or modify. Each rule contains:

  • An EgressRuleMatch clause defining trigger conditions
  • An EgressRuleAction clause defining the resulting operation

The network-agent evaluates rules in order, implementing first-match-wins semantics. Once a request satisfies a match condition, the corresponding action executes and evaluation stops.

EgressRuleMatch – Domain Allowlisting Logic

Domain allowlisting lives inside the EgressRuleMatch struct (line 138). This component supports matching on:

  • SNI (Server Name Indication)
  • Host (IP addresses, CIDR ranges, exact domains, or wildcards like *.example.com)
  • Path and Method for HTTP-specific filtering

The helper function extractL7AllowOutTargetsFromRules in service.go walks the rule slice to collect all allowed destinations for bookkeeping and validation purposes.

EgressRuleAction and EgressRuleInject – Credential Injection

When a match succeeds, the EgressRuleAction struct (line 148) determines the outcome. The action can:

  • Allow the request (Allow: true)
  • Inject credentials via the Inject field containing a slice of EgressRuleInject objects

The EgressRuleInject struct (line 155) defines the credential-injection descriptor with fields for the header name, value, and optional secret references (e.g., ${TOKEN}). The embedded Lua bootstrap in CubeEgress expands these values into HTTP request headers before forwarding to the downstream service.

How Domain Allowlisting Works

When a request enters the CubeSandbox network stack, CubeEgress evaluates the rule list against the connection attributes:

  1. The Host field of EgressRuleMatch accepts plain domains (api.example.com), CIDR notation (10.0.0.0/8), or wildcard patterns (*.internal.com)
  2. The engine performs string matching against the SNI or HTTP Host header
  3. The first matching rule determines the fate of the connection

This approach allows administrators to implement strict egress controls, permitting connections only to explicitly enumerated external APIs or internal services.

How Credential Injection Works

Credential injection operates as a modifier on allowed requests:

  1. If a rule's action.inject slice is non-empty, CubeEgress prepares header injection
  2. Each EgressRuleInject specifies the header name and value, which can contain interpolation syntax for dynamic secrets
  3. The network-agent expands these templates (e.g., "Bearer ${TOKEN}") before the policy reaches CubeEgress
  4. CubeEgress attaches the resolved headers to the HTTP request before forwarding

This mechanism enables secure authentication to external APIs without exposing credentials to the sandboxed workload.

Policy Lifecycle and Push Mechanism

The network-agent manages the transition from configuration to active enforcement through a resilient push mechanism.

Configuration Conversion

The CubeNetworkConfig struct converts to the CubeEgress admin API format via toEgressInput. This conversion:

  • Clones rule slices to prevent mutability bugs
  • Drops nil fields to minimize payload size
  • Validates rule consistency before transmission

The unit test TestToEgressInputDropsNilFields verifies this sanitization logic.

Best-Effort Push and Retry

The pushEgressForState function issues a PUT request to the CubeEgress admin endpoint at /policy/<sandbox-ip>. This operation is best-effort:

  • Transient failures set the pendingEgressPush flag
  • The lifecycle loop invokes retryPendingEgressPushes (defined in tap_lifecycle.go) to retry failed pushes
  • Permanent errors clear the flag to prevent infinite retry loops

The test TestPushEgressForStateSuccessClearsPending validates this state machine behavior.

Code Implementation Examples

Creating Rule Lists in Go

rules := []*network_agent.EgressRule{
    {
        Match:  &network_agent.EgressRuleMatch{Host: ptr("api.example.com")},
        Action: &network_agent.EgressRuleAction{Allow: true},
    },
    {
        Match:  &network_agent.EgressRuleMatch{Host: ptr("private.internal")},
        Action: &network_agent.EgressRuleAction{
            Allow: true,
            Inject: []*network_agent.EgressRuleInject{
                {Header: "Authorization", Value: "Bearer ${TOKEN}"},
            },
        },
    },
}

cfg := &network_agent.CubeNetworkConfig{
    SandboxID: "sb-01",
    SandboxIP: "10.0.2.3",
    Rules:     rules,
}

Pushing the Policy

svc := network_agent.NewService(cfg) // builds local_service with egress client

if err := svc.PushEgressForState(ctx, state); err != nil {
    log.Fatalf("failed to push egress: %v", err)
}

Policy JSON Structure

{
  "rules": [
    {
      "match": { "host": "api.example.com" },
      "action": { "allow": true }
    },
    {
      "match": { "host": "private.internal" },
      "action": {
        "allow": true,
        "inject": [{ "header": "Authorization", "value": "Bearer ${TOKEN}" }]
      }
    }
  ]
}

Summary

  • CubeEgress operates as an L7 firewall inside the CubeSandbox network stack, implementing first-match-wins rule evaluation
  • Domain allowlisting uses EgressRuleMatch.Host with support for IPs, CIDRs, domains, and wildcards as defined in network-agent/internal/service/types.go
  • Credential injection occurs via EgressRuleInject, which adds HTTP headers before forwarding requests to external services
  • Policy propagation follows a best-effort push model with pendingEgressPush retry logic managed in tap_lifecycle.go
  • The conversion layer in local_service.go ensures immutable rule cloning and nil-field sanitization before transmission to the CubeEgress admin API

Frequently Asked Questions

How does CubeEgress resolve conflicts between overlapping rules?

CubeEgress evaluates the EgressRule slice sequentially, implementing first-match-wins semantics. When a request satisfies the EgressRuleMatch conditions of multiple rules, only the action of the first matching rule executes. Administrators must order rules from most specific to least specific to ensure correct policy enforcement.

What credential sources does CubeEgress support for header injection?

The EgressRuleInject struct supports static values and dynamic interpolation via the ${VARIABLE} syntax. The network-agent expands these references from environment variables or secrets before pushing the policy to CubeEgress. The actual header injection occurs within the CubeEgress Lua bootstrap before the request leaves the sandbox network.

Where is the retry logic implemented for failed policy pushes?

The retry mechanism resides in network-agent/internal/service/local_service.go and tap_lifecycle.go. The pushEgressForState function sets a pendingEgressPush flag when transient errors occur, and the lifecycle loop calls retryPendingEgressPushes to re-attempt transmission. Permanent errors clear this flag to prevent infinite retries.

How can I verify which domains are allowed by my current policy?

Use the DumpEgressPolicies function or examine the extractL7AllowOutTargetsFromRules helper in service.go. This function walks the rule list and extracts all allowed destinations, returning the complete set of domains, IPs, and CIDR ranges that the sandbox can reach through the egress firewall.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →