Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cns/NetworkContainerContract.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const (

// CreateNetworkContainerRequest specifies request to create a network container or network isolation boundary.
type CreateNetworkContainerRequest struct {
HostPrimaryIP string
Version string
NetworkContainerType string
NetworkContainerid string // Mandatory input.
Expand Down
1 change: 1 addition & 0 deletions cns/configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type CNSConfig struct {
WireserverIP string
KeyVaultSettings KeyVaultSettings
MSISettings MSISettings
ProgramSNATIPTables bool
}

type TelemetrySettings struct {
Expand Down
6 changes: 4 additions & 2 deletions cns/restserver/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,8 @@ func TestGetNetworkContainerVersionStatus(t *testing.T) {
func createNC(
t *testing.T,
params createOrUpdateNetworkContainerParams,
expectError bool) {
expectError bool,
) {
if err := createOrUpdateNetworkContainerWithParams(t, params); err != nil {
t.Errorf("createOrUpdateNetworkContainerWithParams failed Err:%+v", err)
t.Fatal(err)
Expand Down Expand Up @@ -658,7 +659,8 @@ func publishNCViaCNS(t *testing.T,
networkID,
networkContainerID,
createNetworkContainerURL string,
expectError bool) error {
expectError bool,
) error {
var (
body bytes.Buffer
resp cns.PublishNetworkContainerResponse
Expand Down
63 changes: 63 additions & 0 deletions cns/restserver/internalapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"encoding/json"
"fmt"
"net"
"net/http"
"net/http/httptest"
"reflect"
Expand All @@ -20,6 +21,8 @@ import (
"github.com/Azure/azure-container-networking/cns/types"
"github.com/Azure/azure-container-networking/common"
"github.com/Azure/azure-container-networking/crd/nodenetworkconfig/api/v1alpha"
"github.com/Azure/azure-container-networking/iptables"
"github.com/Azure/azure-container-networking/network/networkutils"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -360,5 +363,65 @@ func (service *HTTPRestService) CreateOrUpdateNetworkContainerInternal(req *cns.
logger.Errorf(returnMessage)
}

if service.Options[common.OptProgramSNATIPTables] == true {
returnCode, returnMessage = service.programSNATIPTableRules(req)
if returnCode != 0 {
logger.Errorf(returnMessage)
}
}

return returnCode
}

// nolint
func (service *HTTPRestService) programSNATIPTableRules(req *cns.CreateNetworkContainerRequest) (types.ResponseCode, string) {
service.Lock()
defer service.Unlock()

if service.programmedIPtables { // check if iptables has already been programmed
logger.Printf("[Azure CNS] SNAT IPTables rules already programmed")
return types.Success, ""
}

ncPrimaryIP, ncIPNet, _ := net.ParseCIDR(req.IPConfiguration.IPSubnet.IPAddress + "/" + fmt.Sprintf("%d", req.IPConfiguration.IPSubnet.PrefixLength))

azureDNSUDPMatch := fmt.Sprintf(" -m addrtype ! --dst-type local -s %s -d %s -p %s --dport %d", ncIPNet.String(), networkutils.AzureDNS, iptables.UDP, iptables.DNSPort)
azureDNSTCPMatch := fmt.Sprintf(" -m addrtype ! --dst-type local -s %s -d %s -p %s --dport %d", ncIPNet.String(), networkutils.AzureDNS, iptables.TCP, iptables.DNSPort)
azureIMDSMatch := fmt.Sprintf(" -m addrtype ! --dst-type local -s %s -d %s -p %s --dport %d", ncIPNet.String(), networkutils.AzureIMDS, iptables.TCP, iptables.HTTPPort)

snatPrimaryIPJump := fmt.Sprintf("%s --to %s", iptables.Snat, ncPrimaryIP)
// we need to snat IMDS traffic to node IP, this sets up snat '--to'
snatHostIPJump := fmt.Sprintf("%s --to %s", iptables.Snat, req.HostPrimaryIP)

// Check if iptables rules exist already
if iptables.RuleExists(iptables.V4, iptables.Nat, iptables.Postrouting, "", iptables.Swift) &&
iptables.RuleExists(iptables.V4, iptables.Nat, iptables.Swift, azureDNSUDPMatch, snatPrimaryIPJump) &&
iptables.RuleExists(iptables.V4, iptables.Nat, iptables.Swift, azureDNSTCPMatch, snatPrimaryIPJump) &&
iptables.RuleExists(iptables.V4, iptables.Nat, iptables.Swift, azureIMDSMatch, snatHostIPJump) {

logger.Printf("[Azure CNS] SNAT IPTables rules already programmed")
service.programmedIPtables = true
return types.Success, ""
}

cmds := []iptables.IPTableEntry{
iptables.GetCreateChainCmd(iptables.V4, iptables.Nat, iptables.Swift),
iptables.GetAppendIptableRuleCmd(iptables.V4, iptables.Nat, iptables.Postrouting, "", iptables.Swift),
// add a snat rules to primary NC IP for DNS
iptables.GetInsertIptableRuleCmd(iptables.V4, iptables.Nat, iptables.Swift, azureDNSUDPMatch, snatPrimaryIPJump),
iptables.GetInsertIptableRuleCmd(iptables.V4, iptables.Nat, iptables.Swift, azureDNSTCPMatch, snatPrimaryIPJump),
// add a snat rule to node IP for IMDS http traffic
iptables.GetInsertIptableRuleCmd(iptables.V4, iptables.Nat, iptables.Swift, azureIMDSMatch, snatHostIPJump),
}

logger.Printf("Adding iptable rules...")
for _, cmd := range cmds {
err := iptables.RunCmd(cmd.Version, cmd.Params)
if err != nil {
return types.FailedToRunIPTableCmd, "failed to run iptable cmd: " + err.Error()
}
logger.Printf("Successfully run iptables rule %v", cmd)
}

return types.Success, ""
}
3 changes: 2 additions & 1 deletion cns/restserver/restserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ type HTTPRestService struct {
state *httpRestServiceState
podsPendingIPAssignment *bounded.TimedSet
sync.RWMutex
dncPartitionKey string
dncPartitionKey string
programmedIPtables bool
}

type GetHTTPServiceDataResponse struct {
Expand Down
6 changes: 4 additions & 2 deletions cns/restserver/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,8 @@ func (service *HTTPRestService) updateIPConfigsStateUntransacted(
// If the IP is already added then it will be an idempotent call. Also note, caller will
// acquire/release the service lock.
func (service *HTTPRestService) addIPConfigStateUntransacted(ncID string, hostVersion int, ipconfigs,
existingSecondaryIPConfigs map[string]cns.SecondaryIPConfig) {
existingSecondaryIPConfigs map[string]cns.SecondaryIPConfig,
) {
// add ipconfigs to state
for ipID, ipconfig := range ipconfigs {
// New secondary IP configs has new NC version however, CNS don't want to override existing IPs'with new
Expand Down Expand Up @@ -628,7 +629,8 @@ func (service *HTTPRestService) setNetworkStateJoined(networkID string) {

// Join Network by calling nmagent
func (service *HTTPRestService) joinNetwork(
networkID string) (*http.Response, error, error) {
networkID string,
) (*http.Response, error, error) {
var err error
joinResponse, joinErr := nmagent.JoinNetwork(networkID)

Expand Down
1 change: 1 addition & 0 deletions cns/service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ func main() {
httpRestService.SetOption(acn.OptCreateDefaultExtNetworkType, createDefaultExtNetworkType)
httpRestService.SetOption(acn.OptHttpConnectionTimeout, httpConnectionTimeout)
httpRestService.SetOption(acn.OptHttpResponseHeaderTimeout, httpResponseHeaderTimeout)
httpRestService.SetOption(acn.OptProgramSNATIPTables, cnsconfig.ProgramSNATIPTables)

// Create default ext network if commandline option is set
if len(strings.TrimSpace(createDefaultExtNetworkType)) > 0 {
Expand Down
1 change: 1 addition & 0 deletions cns/singletenantcontroller/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func CreateNCRequestFromDynamicNC(nc v1alpha.NetworkContainer) (*cns.CreateNetwo
}
}
return &cns.CreateNetworkContainerRequest{
HostPrimaryIP: nc.NodeIP,
SecondaryIPConfigs: secondaryIPConfigs,
NetworkContainerid: nc.ID,
NetworkContainerType: cns.Docker,
Expand Down
1 change: 1 addition & 0 deletions cns/types/codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const (
NetworkContainerVfpProgramCheckSkipped ResponseCode = 36
NmAgentSupportedApisError ResponseCode = 37
UnsupportedNCVersion ResponseCode = 38
FailedToRunIPTableCmd ResponseCode = 39
UnexpectedError ResponseCode = 99
)

Expand Down
3 changes: 3 additions & 0 deletions common/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ const (
OptTelemetry = "telemetry"
OptTelemetryAlias = "dt"

// Enable CNS to program SNAT iptables rules
OptProgramSNATIPTables = "program-snat-iptables"

// Enable Telemetry service
OptTelemetryService = "telemetry-service"
OptTelemetryServiceAlias = "ts"
Expand Down