Beispiel #1
0
// 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
}
Beispiel #2
0
// 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
}
Beispiel #3
0
// 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
}
Beispiel #4
0
// 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
}
Beispiel #5
0
// 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
}
Beispiel #6
0
// 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
}
Beispiel #7
0
// 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
}
Beispiel #8
0
// 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
}
Beispiel #9
0
// 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
	}
}
Beispiel #10
0
// 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
}
Beispiel #11
0
// 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
}