// 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 }
// addIPtablesRuleUnsafe is a non thread safe implementation of addIPtablesRule. // Unsafe implementation is needed for functions which are already managing same mutex. func (firewallStore *firewallStore) addIPtablesRuleUnsafe(rule *IPtablesRule) error { db := firewallStore.DbStore.Db // db := firewallStore.GetDb() log.Info("In addIPtablesRule() after GetDb") if db == nil { panic("In addIPtablesRule(), db is nil") } firewallStore.DbStore.Db.Create(rule) log.Info("In addIPtablesRule() after Db.Create") if db.Error != nil { return db.Error } firewallStore.DbStore.Db.NewRecord(*rule) err := common.MakeMultiError(db.GetErrors()) if err != nil { return err } if db.Error != nil { return db.Error } return nil }
// ProvisionEndpoint creates iptables Rules for given endpoint in given environment func (fw IPtables) ProvisionEndpoint() error { log.Info("In ProvisionEndpoint() with firewall.") if !fw.initialized { return fmt.Errorf("In ProvisionEndpoint(), can not provision uninitialized firewall, use Init()") } err := fw.CreateChains(fw.chains) if err != nil { return err } log.Info("Firewall: creating rules") for chain := range fw.chains { if err := fw.CreateRules(chain); err != nil { return err } } if err := fw.CreateDefaultDropRule(ForwardOutChainIndex); err != nil { return err } log.Info("Firewall: diverting traffic") for _, chain := range fw.chains { if err := fw.DivertTrafficToRomanaIPtablesChain(chain, installDivertRules); err != nil { 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 }
func (l *KubeListener) Initialize(client *common.RestClient) error { l.restClient = client // TODO, find a better place to initialize // the translator. Stas. PTranslator.Init(l.restClient, l.segmentLabelName, l.tenantLabelName) tc := PTranslator.GetClient() if tc == nil { log.Critical("Failed to initialize rest client for policy translator.") os.Exit(255) } l.lastEventPerNamespace = make(map[string]uint64) log.Infof("%s: Starting server", l.Name()) nsURL, err := common.CleanURL(fmt.Sprintf("%s/%s/?%s", l.kubeURL, l.namespaceNotificationPath, HttpGetParamWatch)) if err != nil { return err } log.Infof("Starting to listen on %s", nsURL) done := make(chan struct{}) eventc, err := l.nsWatch(done, nsURL) if err != nil { log.Critical("Namespace watcher failed to start", err) os.Exit(255) } // events := l.conductor(nsEvents, done) l.process(eventc, done) ProduceNewPolicyEvents(eventc, done, l) log.Info("All routines started") 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 }
func (firewallStore *firewallStore) addIPtablesRule(rule *IPtablesRule) error { log.Info("Acquiring store mutex for addIPtablesRule") if rule == nil { panic("In addIPtablesRule(), received nil rule") } firewallStore.mu.Lock() defer func() { log.Info("Releasing store mutex for addIPtablesRule") firewallStore.mu.Unlock() }() log.Info("Acquired store mutex for addIPtablesRule") err := firewallStore.addIPtablesRuleUnsafe(rule) return err }
// listIPtablesRules returns a list of all firewall rules in a database. func (firewallStore *firewallStore) listIPtablesRules() ([]IPtablesRule, error) { log.Info("Acquiring store mutex for listIPtablesRules") firewallStore.mu.Lock() defer func() { log.Info("Releasing store mutex for listIPtablesRules") firewallStore.mu.Unlock() }() log.Info("Acquired store mutex for listIPtablesRules") var iPtablesRule []IPtablesRule firewallStore.DbStore.Db.Find(&iPtablesRule) err := common.MakeMultiError(firewallStore.DbStore.Db.GetErrors()) if err != nil { return nil, err } return iPtablesRule, nil }
// EnsureRule verifies if given iptables rule exists and creates if it's not. func (fw IPtables) EnsureRule(rule FirewallRule, opType RuleState) error { ruleExists := fw.isRuleExist(rule) args := []string{} if ruleExists { switch opType { case EnsureAbsent: args = append(args, "-D") default: log.Info("In EnsureRule - nothing to do ", rule.GetBody()) return nil } } else { switch opType { case EnsureLast: args = append(args, "-A") case EnsureFirst: args = append(args, "-I") default: log.Info("In EnsureRule - nothing to do ", rule.GetBody()) return nil } } args = append(args, strings.Split(rule.GetBody(), " ")...) cmdStr := iptablesCmd + " " + strings.Join(args, " ") out, err := fw.os.Exec(iptablesCmd, args) if err != nil { log.Errorf("[%s]: %s failed for rule %s with error %v, saying [%s]", cmdStr, opType, rule.GetBody(), err, string(out)) } else { if out != nil && len(out) > 0 { log.Infof("%s success %s: [%s]", opType, rule.GetBody(), string(out)) } else { log.Infof("%s success %s", opType, rule.GetBody()) } } return err }
// deleteIPtablesRule deletes firewall rules from database. func (firewallStore *firewallStore) deleteIPtablesRule(rule *IPtablesRule) error { log.Info("Acquiring store mutex for deleteIPtablesRule") firewallStore.mu.Lock() defer func() { log.Info("Releasing store mutex for deleteIPtablesRule") firewallStore.mu.Unlock() }() log.Info("Acquired store mutex for deleteIPtablesRule") db := firewallStore.DbStore.Db firewallStore.DbStore.Db.Delete(rule) err := common.MakeMultiError(db.GetErrors()) if err != nil { return err } if db.Error != nil { return db.Error } return nil }
// switchIPtablesRule changes IPtablesRule state. func (firewallStore *firewallStore) switchIPtablesRule(rule *IPtablesRule, op opSwitchIPtables) error { // Fast track return if nothing to be done if rule.State == op.String() { log.Infof("switchIPtablesRule nothing to be done for %s", rule.State) return nil } log.Info("Acquiring store mutex for switchIPtablesRule") firewallStore.mu.Lock() defer func() { log.Info("Releasing store mutex for switchIPtablesRule") firewallStore.mu.Unlock() }() log.Info("Acquired store mutex for switchIPtablesRule") // if toggle requested then reverse current state if op == toggleRule { if rule.State == setRuleInactive.String() { rule.State = setRuleActive.String() } else { rule.State = setRuleInactive.String() } // otherwise just assign op value } else { rule.State = op.String() } db := firewallStore.DbStore.Db firewallStore.DbStore.Db.Save(rule) err := common.MakeMultiError(db.GetErrors()) if err != nil { return err } if db.Error != nil { return db.Error } return nil }
func (firewallStore *firewallStore) findIPtablesRules(subString string) (*[]IPtablesRule, error) { log.Info("Acquiring store mutex for findIPtablesRule") firewallStore.mu.Lock() defer func() { log.Info("Releasing store mutex for findIPtablesRule") firewallStore.mu.Unlock() }() log.Info("Acquired store mutex for findIPtablesRule") var rules []IPtablesRule db := firewallStore.DbStore.Db searchString := "%" + subString + "%" firewallStore.DbStore.Db.Where("body LIKE ?", searchString).Find(&rules) err := common.MakeMultiError(db.GetErrors()) if err != nil { return nil, err } if db.Error != nil { return nil, db.Error } return &rules, nil }
// ensureIPtablesRule checks if given rule exists in a database and if not, creates it. func (firewallStore *firewallStore) ensureIPtablesRule(rule *IPtablesRule) error { log.Info("Acquiring store mutex for listIPtablesRules") firewallStore.mu.Lock() defer func() { log.Info("Releasing store mutex for listIPtablesRules") firewallStore.mu.Unlock() }() log.Info("Acquired store mutex for listIPtablesRules") if firewallStore.DbStore.Db.Where("body = ?", rule.Body).First(rule).RecordNotFound() { log.Tracef(trace.Inside, "In ensureIPtablesRule(), rule %s not found in db - creating", rule.Body) err0 := firewallStore.addIPtablesRuleUnsafe(rule) if err0 != nil { log.Errorf("In ensureIPtablesRule() failed to store rule %v", rule) return err0 } } else { log.Tracef(trace.Inside, "In ensureIPtablesRule(), rule %s already in db - nothing to do", rule.Body) } 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 }
func (agentStore *agentStore) addRoute(route *Route) error { log.Info("Acquiring store mutex for addRoute") agentStore.mu.Lock() defer func() { log.Info("Releasing store mutex for addRoute") agentStore.mu.Unlock() }() log.Info("Acquired store mutex for addRoute") db := agentStore.DbStore.Db agentStore.DbStore.Db.Create(route) if db.Error != nil { return db.Error } agentStore.DbStore.Db.NewRecord(*route) err := common.MakeMultiError(db.GetErrors()) if err != nil { return err } if db.Error != nil { return db.Error } return nil }
// updateCache contacts romana Tenant service, lists // all resources and loads them into memory. func (t *Translator) updateCache() error { log.Info("In updateCache") tenantURL, err := t.restClient.GetServiceUrl("tenant") if err != nil { return TranslatorError{ErrorCacheUpdate, err} } tenants := []tenant.Tenant{} err = t.restClient.Get(tenantURL+"/tenants", &tenants) if err != nil { log.Errorf("updateCache(): Error getting tenant information: %s", err) return TranslatorError{ErrorCacheUpdate, err} } if t.restClient == nil { log.Critical("REST client is nil") os.Exit(255) } // tenants := []tenant.Tenant{} // _ = t.restClient.Find(&tenants, common.FindAll) t.cacheMu.Lock() defer func() { log.Infof("Exiting updateCache with %d tenants", len(t.tenantsCache)) t.cacheMu.Unlock() }() t.tenantsCache = nil for _, ten := range tenants { segments := []tenant.Segment{} fullUrl := fmt.Sprintf("%s/tenants/%d/segments", tenantURL, ten.ID) err = t.restClient.Get(fullUrl, &segments) // ignore 404 error here which means no segments // considered to be a zero segments rather then // an error. if err != nil && !checkHttp404(err) { log.Errorf("updateCache(): Error getting segment information for tenant %d: %s", ten.ID, err) return TranslatorError{ErrorCacheUpdate, err} } t.tenantsCache = append(t.tenantsCache, TenantCacheEntry{ten, segments}) } 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 }
// Kube2RomanaBulk attempts to translate a list of kubernetes policies into // romana representation, returns a list of translated policies and a list // of policies that can't be translated in original format. func (t Translator) Kube2RomanaBulk(kubePolicies []v1beta1.NetworkPolicy) ([]common.Policy, []v1beta1.NetworkPolicy, error) { log.Info("In Kube2RomanaBulk") var returnRomanaPolicy []common.Policy var returnKubePolicy []v1beta1.NetworkPolicy err := t.updateCache() if err != nil { return returnRomanaPolicy, returnKubePolicy, TranslatorError{ErrorCacheUpdate, err} } for kubePolicyNumber, _ := range kubePolicies { romanaPolicy, err := t.translateNetworkPolicy(&kubePolicies[kubePolicyNumber]) if err != nil { log.Errorf("Error during policy translation %s", err) returnKubePolicy = append(returnKubePolicy, kubePolicies[kubePolicyNumber]) } else { returnRomanaPolicy = append(returnRomanaPolicy, romanaPolicy) } } return returnRomanaPolicy, returnKubePolicy, nil }