// CreateRules creates iptables Rules for the given Romana chain // to allow a traffic to flow between the Host and Endpoint. func (fw *IPtables) CreateRules(chain int) error { log.Info("In CreateRules() for chain", chain) for _, rule := range fw.chains[chain].Rules { // First create rule record in database. err0 := fw.addIPtablesRule(rule) if err0 != nil { log.Error("In CreateRules() create db record for iptables rule ", rule.GetBody()) return err0 } err1 := fw.EnsureRule(rule, EnsureFirst) if err1 != nil { log.Error("In CreateRules() failed to create install firewall rule ", rule.GetBody()) return err1 } // Finally, set 'active' flag in database record. if err2 := fw.Store.switchIPtablesRule(rule, setRuleActive); err2 != nil { log.Error("In CreateRules() iptables rule created, but activation failed ", rule.GetBody()) return err2 } } log.Info("Creating firewall rules success") return nil }
// CreateDefaultRule creates iptables rule for a chain with the // specified target func (fw *IPtables) CreateDefaultRule(chain int, target string) error { log.Infof("In CreateDefaultRule() %s rules for chain %d", target, chain) chainName := fw.chains[chain].ChainName body := fmt.Sprintf("%s %s %s", chainName, "-j", target) rule := &IPtablesRule{ Body: body, State: setRuleInactive.String(), } // First create rule record in database. err0 := fw.addIPtablesRule(rule) if err0 != nil { log.Error("In CreateDefaultRule() create db record for iptables rule ", rule.GetBody()) return err0 } err1 := fw.EnsureRule(rule, EnsureLast) if err1 != nil { log.Errorf("In CreateDefaultRule() %s rules failed", target) return err1 } // Finally, set 'active' flag in database record. if err2 := fw.Store.switchIPtablesRule(rule, setRuleActive); err2 != nil { log.Error("In CreateDefaultRule() iptables rule created but activation failed ", rule.GetBody()) return err2 } log.Info("In CreateDefaultRule() success") return nil }
// addIPtablesRule creates new iptable rule in database. func (fw *IPtables) addIPtablesRule(rule *IPtablesRule) error { if err := fw.Store.addIPtablesRule(rule); err != nil { log.Error("In addIPtablesRule failed to add ", rule.GetBody()) return err } return nil }
// CreateU32Rules creates wildcard iptables Rules for the given Romana chain. // These Rules serve to restrict traffic between segments and tenants. // * Deprecated, outdated * func (fw *IPtables) CreateU32Rules(chain int) error { log.Info("Creating U32 firewall rules for chain", chain) chainName := fw.chains[chain].ChainName args := []string{"-w", "-A", chainName, "-m", "u32", "--u32", fw.u32filter, "-j", "ACCEPT"} _, err := fw.os.Exec(iptablesCmd, args) if err != nil { log.Error("Creating U32 firewall rules failed") return err } log.Info("Creating U32 firewall rules success") return nil }
// Initialize implements the Initialize method of common.Service // interface. func (a *Agent) Initialize(client *common.RestClient) error { log.Trace(trace.Public, "Entering Agent.Initialize()") err := a.store.Connect() if err != nil { log.Error("Agent.Initialize() : Failed to connect to database.") return err } log.Info("Agent: Attempting to identify current host.") if err := a.identifyCurrentHost(); err != nil { log.Error("Agent: ", agentError(err)) return agentError(err) } a.client = client // Ensure we have all the routes to our neighbours log.Info("Agent: ensuring interhost routes exist") if err := a.Helper.ensureInterHostRoutes(); err != nil { log.Error("Agent: ", agentError(err)) return agentError(err) } return nil }
// deleteIPtablesRule attempts to uninstall and delete the given rule. func (fw *IPtables) deleteIPtablesRule(rule *IPtablesRule) error { if err := fw.Store.switchIPtablesRule(rule, setRuleInactive); err != nil { log.Error("In deleteIPtablesRule() failed to deactivate the rule", rule.GetBody()) return err } if err1 := fw.EnsureRule(rule, EnsureAbsent); err1 != nil { log.Errorf("In deleteIPtablesRule() rule %s set inactive but failed to uninstall", rule.GetBody()) return err1 } if err2 := fw.Store.deleteIPtablesRule(rule); err2 != nil { log.Errorf("In deleteIPtablesRule() rule %s set inactive and uninstalled but failed to delete DB record", rule.GetBody()) return err2 } return nil }
// DivertTrafficToRomanaIPtablesChain injects iptables Rules to send traffic // into the ROMANA chain. // We need to do this for each tenant/segment pair as each pair will have different chain name. func (fw *IPtables) DivertTrafficToRomanaIPtablesChain(chain IPtablesChain, opType opDivertTrafficAction) error { // Should be like that // iptables -A INPUT -i tap1234 -j ROMANA-T0S1-INPUT log.Infof("In DivertTrafficToRomanaIPtablesChain() processing chain %v with state %s", chain, opType) var state RuleState switch opType { case installDivertRules: state = EnsureLast case removeDivertRules: state = EnsureAbsent } // baseChain := fw.chains[chain].BaseChain for _, directionLiteral := range chain.Directions { direction := fmt.Sprintf("-%s", directionLiteral) body := fmt.Sprintf("%s %s %s %s %s", chain.BaseChain, direction, fw.interfaceName, "-j", chain.ChainName) rule := &IPtablesRule{ Body: body, State: setRuleInactive.String(), } // First create rule record in database. err0 := fw.addIPtablesRule(rule) if err0 != nil { log.Errorf("In DivertTrafficToRomanaIPtablesChain() failed to process chain %v", chain) return err0 } // Then create actuall rule in the system. if err1 := fw.EnsureRule(rule, state); err1 != nil { log.Errorf("In DivertTrafficToRomanaIPtablesChain() failed to process chain %v", chain) return err1 } // Finally, set 'active' flag in database record. if err2 := fw.Store.switchIPtablesRule(rule, setRuleActive); err2 != nil { log.Error("In DivertTrafficToRomanaIPtablesChain() iptables rule created but activation failed ", rule.GetBody()) return err2 } } log.Info("DivertTrafficToRomanaIPtablesChain() successfully processed chain number", chain) return nil }
// vmDownHandler handles HTTP requests for endpoints teardown. func (a *Agent) vmDownHandler(input interface{}, ctx common.RestContext) (interface{}, error) { log.Tracef(trace.Private, "In vmDownHandler() with %T %v", input, input) netif := input.(*NetIf) if netif.Name == "" { // This is a request from OpenStack Mech driver who does not have a name, // let's find it by mac. err := a.store.findNetIf(netif) if err != nil { return nil, err } } log.Infof("Agent: Provisioning DHCP for %s, IP %s Mac %s\n", netif.Name, netif.IP, netif.Mac) if err := a.leaseFile.provisionLease(netif, leaseRemove); err != nil { log.Error(agentError(err)) return "Error removing DHCP lease", agentError(err) } // We need new firewall instance here to use it's Cleanup() // to uninstall firewall rules related to the endpoint. fw, err := firewall.NewFirewall(a.getFirewallType()) if err != nil { return nil, err } err = fw.Init(a.Helper.Executor, a.store, a.networkConfig) if err != nil { return nil, err } err = fw.Cleanup(netif) if err != nil { return nil, err } err = a.store.deleteNetIf(netif) if err != nil { return nil, err } return "OK", nil }
// getOrAddSegment finds a segment (based on segment selector). // If not found, it adds one. func (l *Translator) getOrAddSegment(namespace string, kubeSegmentName string) (*tenant.Segment, error) { tenantCacheEntry := l.checkTenantInCache(namespace) if tenantCacheEntry == nil { return nil, TranslatorError{ErrorTenantNotInCache, fmt.Errorf("Tenant not found in cache while resolving segment")} } segment := l.checkSegmentInCache(tenantCacheEntry, kubeSegmentName) if segment != nil { // Stop right here, we have what we // came for. return segment, nil } // This branch corresponds to a situation when // tenant found in the cache but segment isn't. // We will try to create a segment and update the cache. defer func() { err := l.updateCache() if err != nil { log.Error("Failed to update cache in translator during getOrAddSegment().") } }() ten := tenantCacheEntry.Tenant seg := &tenant.Segment{} seg.Name = kubeSegmentName seg.TenantID = ten.ID err := l.restClient.Find(seg, common.FindExactlyOne) if err == nil { return seg, nil } switch err := err.(type) { case common.HttpError: if err.StatusCode == http.StatusNotFound { // Not found, so let's create a segment. segreq := tenant.Segment{Name: kubeSegmentName, TenantID: ten.ID} segURL, err2 := l.restClient.GetServiceUrl("tenant") if err2 != nil { return nil, err2 } segURL = fmt.Sprintf("%s/tenants/%d/segments", segURL, ten.ID) err2 = l.restClient.Post(segURL, segreq, seg) if err2 == nil { // Successful creation. return seg, nil } // Creation of non-existing segment gave an error. switch err2 := err2.(type) { case common.HttpError: // Maybe someone else just created a segment between the original // lookup and now? if err2.StatusCode == http.StatusConflict { switch details := err2.Details.(type) { case tenant.Segment: // We expect the existing segment to be returned in the details field. return &details, nil default: // This is unexpected... return nil, err } } // Any other HTTP error other than a Conflict here - return it. return nil, err2 default: // Any other error - return it return nil, err2 } } // Any other HTTP error other than a Not found here - return it return nil, err default: // Any other error - return it return nil, err } }
// vmUpHandlerAsync does a number of operations on given endpoint to ensure // it's connected: // 1. Ensures interface is ready // 2. Checks if DHCP is running // 3. Creates ip route pointing new interface // 4. Provisions static DHCP lease for new interface // 5. Provisions firewall rules func (a *Agent) vmUpHandlerAsync(netif NetIf) error { log.Trace(trace.Private, "Agent: Entering interfaceHandle()") currentProvider := a.getFirewallType() if !a.Helper.waitForIface(netif.Name) { // TODO should we resubmit failed interface in queue for later // retry ? ... considering oenstack will give up as well after // timeout return agentErrorString(fmt.Sprintf("Requested interface not available in time - %s", netif.Name)) } // dhcpPid is only needed here for fail fast check // will try to poll the pid again in provisionLease log.Trace(trace.Inside, "Agent: Checking if DHCP is running") _, err := a.Helper.DhcpPid() if err != nil { log.Error(agentError(err)) return agentError(err) } err = a.store.addNetIf(&netif) if err != nil { return agentError(err) } log.Infof("Agent: Creating endpoint routes - %s", netif.Name) if err := a.Helper.ensureRouteToEndpoint(&netif); err != nil { log.Error(agentError(err)) return agentError(err) } log.Infof("Agent: Provisioning DHCP - %s", netif.Name) if err := a.leaseFile.provisionLease(&netif, leaseAdd); err != nil { log.Error(agentError(err)) return agentError(err) } log.Infof("Agent: Provisioning firewall - %s", netif.Name) fw, err := firewall.NewFirewall(currentProvider) if err != nil { return err } err = fw.Init(a.Helper.Executor, a.store, a.networkConfig) if err != nil { log.Error(agentError(err)) return agentError(err) } if err1 := fw.SetEndpoint(netif); err1 != nil { log.Error(agentError(err1)) return agentError(err1) } var rules RuleSet switch currentProvider { case firewall.ShellexProvider: rules = OpenStackShellRules case firewall.IPTsaveProvider: rules = OpenStackSaveRestoreRules default: err := fmt.Errorf("Unkown firewall provider in vmUpHandler") log.Error(agentError(err)) return agentError(err) } if err := prepareFirewallRules(fw, a.networkConfig, rules, currentProvider); err != nil { log.Error(agentError(err)) return agentError(err) } if err := fw.ProvisionEndpoint(); err != nil { log.Error(agentError(err)) return agentError(err) } log.Trace(trace.Inside, "All good", netif) return nil }
// podUpHandlerAsync does a number of operations on given endpoint to ensure // it's connected: // 1. Ensures interface is ready // 2. Creates ip route pointing new interface // 3. Provisions firewall rules func (a *Agent) podUpHandlerAsync(netReq NetworkRequest) error { log.Trace(trace.Private, "Agent: Entering podUpHandlerAsync()") currentProvider := a.getFirewallType() netif := netReq.NetIf if netif.Name == "" { return agentErrorString("Agent: Interface name required") } if !a.Helper.waitForIface(netif.Name) { // TODO should we resubmit failed interface in queue for later // retry ? ... considering openstack will give up as well after // timeout msg := fmt.Sprintf("Requested interface not available in time - %s", netif.Name) log.Warn("Agent: ", msg) return agentErrorString(msg) } log.Infof("Agent: Creating endpoint routes - %s", netif.Name) if err := a.Helper.ensureRouteToEndpoint(&netif); err != nil { log.Error(agentError(err)) return agentError(err) } log.Infof("Agent: Provisioning firewall - %s", netif.Name) fw, err := firewall.NewFirewall(currentProvider) if err != nil { return err } err = fw.Init(a.Helper.Executor, a.store, a.networkConfig) if err != nil { return err } if err1 := fw.SetEndpoint(netif); err1 != nil { log.Error(agentError(err)) return agentError(err) } var rules RuleSet switch currentProvider { case firewall.ShellexProvider: rules = KubeShellXRules case firewall.IPTsaveProvider: rules = KubeSaveRestoreRules default: err := fmt.Errorf("Unkown firewall provider in podUpHandler") log.Error(agentError(err)) return agentError(err) } if err := prepareFirewallRules(fw, a.networkConfig, rules, currentProvider); err != nil { log.Error(agentError(err)) return agentError(err) } if err := fw.ProvisionEndpoint(); err != nil { log.Error(agentError(err)) return agentError(err) } log.Trace(trace.Inside, "Agent: All good", netif) return nil }