Example #1
0
// process is a goroutine that consumes resource update events coming from
// Kubernetes and:
// 1. On receiving an added or deleted event:
//    i. add it to the queue
//    ii. on a timer event, send the events to handleNetworkPolicyEvents and empty the queue
// 2. On receiving a done event, exit the goroutine
func (l *KubeListener) process(in <-chan Event, done chan struct{}) {
	log.Infof("KubeListener: process(): Entered with in %v, done %v", in, done)

	timer := time.Tick(processorTickTime * time.Second)
	var networkPolicyEvents []Event

	go func() {
		for {
			select {
			case <-timer:
				if len(networkPolicyEvents) > 0 {
					log.Infof("Calling network policy handler for scheduled %d events", len(networkPolicyEvents))
					handleNetworkPolicyEvents(networkPolicyEvents, l)
					networkPolicyEvents = nil
				}
			case e := <-in:
				log.Infof("KubeListener: process(): Got %v", e)
				switch obj := e.Object.(type) {
				case *v1beta1.NetworkPolicy:
					log.Tracef(trace.Inside, "Scheduing network policy action, now scheduled %d actions", len(networkPolicyEvents))
					networkPolicyEvents = append(networkPolicyEvents, e)
				case *v1.Namespace:
					log.Tracef(trace.Inside, "Processor received namespace")
					handleNamespaceEvent(e, l)
				default:
					log.Errorf("Processor received an event of unkonwn type %s, ignoring object %s", reflect.TypeOf(obj), obj)
				}
			case <-done:
				log.Infof("KubeListener: process(): Got done")
				return
			}
		}
	}()
	return
}
Example #2
0
// Init implements Firewall interface
func (i *IPTsaveFirewall) Init(exec utilexec.Executable, store FirewallStore, nc NetConfig) error {
	log.Infof("In Init()")

	fwstore := firewallStore{}
	fwstore.DbStore = store.GetDb()
	fwstore.mu = store.GetMutex()

	i.Store = fwstore
	i.os = exec
	i.networkConfig = nc

	// Read current iptables config.
	output, err := i.os.Exec(iptablesSaveBin, []string{})
	if err != nil {
		log.Infof("In Init(), failed to call iptables-save, %s", err)
		return err
	}

	// Parse iptables-save output.
	i.CurrentState = &iptsave.IPtables{}
	i.CurrentState.Parse(bytes.NewReader(output))

	// Inirialize desired state filter table.
	i.DesiredState = &iptsave.IPtables{}
	i.DesiredState.Tables = append(i.DesiredState.Tables, &iptsave.IPtable{Name: "filter"})
	log.Tracef(trace.Inside, "In Init(), iptables rules loaded\n, %s", i.CurrentState.Render())

	return nil
}
Example #3
0
// HandleDefaultPolicy handles isolation flag on a namespace by creating/deleting
// default network policy. See http://kubernetes.io/docs/user-guide/networkpolicies/
func HandleDefaultPolicy(o *v1.Namespace, l *KubeListener) {
	var defaultDeny bool
	annotationKey := "net.beta.kubernetes.io/networkpolicy"
	if np, ok := o.ObjectMeta.Annotations[annotationKey]; ok {
		log.Infof("Handling default policy on a namespace %s, policy is now %s \n", o.ObjectMeta.Name, np)
		// Annotations are stored in the Annotations map as raw JSON.
		// So we need to parse it.
		isolationPolicy := struct {
			Ingress struct {
				Isolation string `json:"isolation"`
			} `json:"ingress"`
		}{}
		// TODO change to json.Unmarshal. Stas
		err := json.NewDecoder(strings.NewReader(np)).Decode(&isolationPolicy)
		if err != nil {
			log.Errorf("In HandleDefaultPolicy :: Error decoding annotation %s: %s", annotationKey, err)
			return
		}
		log.Debugf("Decoded to policy: %v", isolationPolicy)
		defaultDeny = isolationPolicy.Ingress.Isolation == "DefaultDeny"
	} else {
		log.Infof("Handling default policy on a namespace, no annotation detected assuming non isolated namespace\n")
		defaultDeny = false
	}
	if defaultDeny {
		deleteDefaultPolicy(o, l)
	} else {
		addDefaultPolicy(o, l)
	}
}
Example #4
0
File: store.go Project: romana/core
// getConnStrings returns the appropriate GORM connection string for
// the given DB.
func (dbStore *DbStore) getConnStrings() []string {
	var connStr []string
	info := dbStore.Config
	switch info.Type {
	case "sqlite3":
		connStr = append(connStr, info.Database)
		log.Infof("DB: Connection string: %s", info.Database)
	default:
		portStr := fmt.Sprintf(":%d", info.Port)
		if info.Port == 0 {
			portStr = ":3306"
		}
		connStr = append(connStr, fmt.Sprintf("%s:%s@tcp(%s%s)/%s?parseTime=true",
			info.Username, info.Password, info.Host, portStr, info.Database))
		log.Infof("DB: Connection string: ****:****@tcp(%s%s)/%s?parseTime=true",
			info.Host, portStr, info.Database)
		connStr = append(connStr, fmt.Sprintf("%s:%s@unix(/var/run/mysqld/mysqld.sock)/%s?parseTime=true",
			info.Username, info.Password, info.Database))
		log.Infof("DB: Connection string: ****:****@unix(/var/run/mysqld/mysqld.sock))/%s?parseTime=true",
			info.Database)
		connStr = append(connStr, fmt.Sprintf("%s:%s@unix(/tmp/mysqld.sock)/%s?parseTime=true",
			info.Username, info.Password, info.Database))
		log.Infof("DB: Connection string: ****:****@unix(/tmp/mysqld.sock))/%s?parseTime=true",
			info.Database)
	}
	return connStr
}
Example #5
0
// addDefaultPolicy adds the default policy which is to allow
// all ingres.
func addDefaultPolicy(o *v1.Namespace, l *KubeListener) {
	var err error
	// TODO this should be ExternalID, not Name...
	policyName := getDefaultPolicyName(o)

	// Before adding the default policy, see if it may already exist.
	policy := common.Policy{Name: policyName}

	policyURL, err := l.restClient.GetServiceUrl("policy")
	if err != nil {
		log.Errorf("In addDefaultPolicy :: Failed to find policy service: %s\n", err)
		log.Errorf("In addDefaultPolicy :: Failed to add default policy: %s\n", policyName)
		return
	}

	policyURL = fmt.Sprintf("%s/find/policies/%s", policyURL, policy.Name)
	err = l.restClient.Get(policyURL, &policy)
	if err == nil {
		// An annotation to set isolation off may be issued multiple
		// times and we already have the default policy caused by that in place.
		// So we just do not do anything.
		log.Infof("In addDefaultPolicy :: Policy %s (%d) already exists, ignoring\n", policy.Name, policy.ID)
		return
	}

	// Find tenant, to properly set up policy
	// TODO This really should be by external ID...
	tnt, err := l.resolveTenantByName(o.ObjectMeta.Name)
	if err != nil {
		log.Infof("In addDefaultPolicy :: Error :: failed to resolve tenant %s \n", err)
		return
	}

	romanaPolicy := &common.Policy{
		Direction: common.PolicyDirectionIngress,
		Name:      policyName,
		//		ExternalID: externalID,
		AppliedTo: []common.Endpoint{{TenantNetworkID: &tnt.NetworkID}},
		Ingress: []common.RomanaIngress{
			common.RomanaIngress{
				Peers: []common.Endpoint{{Peer: common.Wildcard}},
				Rules: []common.Rule{{Protocol: common.Wildcard}},
			},
		},
	}

	err = l.addNetworkPolicy(*romanaPolicy)
	switch err := err.(type) {
	default:
		log.Errorf("In addDefaultPolicy :: Error :: failed to create policy  %s: %s\n", policyName, err)
	case nil:
		log.Debugf("In addDefaultPolicy: Succesfully created policy  %s\n", policyName)
	case common.HttpError:
		if err.StatusCode == http.StatusConflict {
			log.Infof("In addDefaultPolicy ::Policy %s already exists.\n", policyName)
		} else {
			log.Errorf("In addDefaultPolicy :: Error :: failed to create policy %s: %s\n", policyName, err)
		}
	}
}
Example #6
0
func (j formMarshaller) Marshal(v interface{}) ([]byte, error) {
	retval := ""
	vPtr := reflect.ValueOf(v)
	vVal := vPtr.Elem()
	vType := reflect.TypeOf(vVal.Interface())
	for i := 0; i < vVal.NumField(); i++ {
		metaField := vType.Field(i)
		field := vVal.Field(i)
		formKey := metaField.Tag.Get("form")
		if len(retval) > 0 {
			retval += "&"
		}
		retval += formKey + "="
		log.Infof("form key of %s is %s\n", metaField.Name, formKey)
		str := ""
		if metaField.Type == stringType {
			str = field.Interface().(string)
		} else {
			toString := field.MethodByName("String")
			log.Infof("Looking for method String on %s: %s\n", field, toString)
			if reflect.Zero(reflect.TypeOf(toString)) != toString {
				toStringResult := toString.Call(nil)
				str = toStringResult[0].String()
			} else {
				log.Infof("Ignoring field %s of %s\n", metaField.Name, v)
				continue
			}
		}
		str = strings.TrimSpace(str)

		retval += str
	}
	return []byte(retval), nil
}
Example #7
0
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
}
Example #8
0
// EnsureRule implements Firewall interface. It schedules given rule for
// transition in given state and stores it in firewall store.
func (i *IPTsaveFirewall) EnsureRule(rule FirewallRule, opType RuleState) error {
	log.Infof("In EnsureRule() with firewall rule %s %s", opType.String(), rule.GetBody())

	var ruleExists bool

	// This firewall only manages filtering rules so it only operates
	// on `filter` table.
	table := i.DesiredState.TableByName("filter")
	if table == nil {
		return fmt.Errorf("In EnsureRule() firewall doesn't have filter table")
	}

	// Convert iptables rule from Firewall interface into iptsave.IPrule.
	tempChain := iptsave.ParseRule(bytes.NewReader([]byte(rule.GetBody())))
	ipRule := tempChain.Rules[0]

	// Ensure that base chain of the rule is defined in desired state.
	chain := table.ChainByName(tempChain.Name)
	if chain == nil {
		table.Chains = append(table.Chains, tempChain)
		chain = tempChain

		// we just added a chain with our rule
		// into the filter table so we know that
		// target rule is in the table.
		ruleExists = true
	}

	// If we didn't put that rule in the table ourselves yet then
	// try to find it in existing table.
	if !ruleExists {
		ruleExists = chain.RuleInChain(ipRule)
	}

	if ruleExists {
		switch opType {
		case EnsureAbsent:
			log.Infof("In EnsureRule - rule %s exists in current state, removing", rule.GetBody())
			chain.DeleteRule(ipRule)
		default:
			log.Infof("In EnsureRule - nothing to do %s", rule.GetBody())
		}
	} else {
		log.Infof("In EnsureRule - rule %s doesn't exist is current state, %s", rule.GetBody(), opType.String())
		switch opType {
		case EnsureLast:
			chain.AppendRule(ipRule)
		case EnsureFirst:
			chain.InsertRule(0, ipRule)
		default:
			log.Infof("In EnsureRule - nothing to do %s", rule.GetBody())
		}
	}

	return nil
}
Example #9
0
// isChainExistByName verifies if given iptables chain exists.
// Returns true if chain exists.
func (fw *IPtables) isChainExistByName(chainName string) bool {
	args := []string{"-w", "-L", chainName}
	output, err := fw.os.Exec(iptablesCmd, args)
	if err != nil {
		log.Infof("isChainExist(): iptables -L %s returned %s", chainName, err)
		return false
	}
	log.Infof("isChainExist(): iptables -L %s returned %s", chainName, string(output))
	return true
}
Example #10
0
// syncNetworkPolicies compares a list of kubernetes network policies with romana network policies,
// it returns a list of kubernetes policies that don't have corresponding kubernetes network policy for them,
// and a list of romana policies that used to represent kubernetes policy but corresponding kubernetes policy is gone.
func (l *KubeListener) syncNetworkPolicies(kubePolicies []v1beta1.NetworkPolicy) (kubernetesEvents []Event, romanaPolicies []common.Policy, err error) {
	log.Infof("In syncNetworkPolicies with %v", kubePolicies)

	policies, err := getAllPoliciesFunc(l.restClient)
	if err != nil {
		return
	}

	log.Infof("In syncNetworkPolicies fetched %d romana policies", len(policies))

	// Compare kubernetes policies and all romana policies by name.
	// TODO Coparing by name is fragile should be `external_id == UID`. Stas.

	// Prepare a list of kubernetes policies that don't have corresponding
	// romana policy.
	var found bool
	accountedRomanaPolicies := make(map[int]bool)

	for kn, kubePolicy := range kubePolicies {
		namespacePolicyNamePrefix := fmt.Sprintf("kube.default.")
		found = false
		for pn, policy := range policies {
			fullPolicyName := fmt.Sprintf("%s%s", namespacePolicyNamePrefix, kubePolicy.ObjectMeta.Name)
			if fullPolicyName == policy.Name {
				found = true
				accountedRomanaPolicies[pn] = true
				break
			}
		}

		if !found {
			log.Tracef(trace.Inside, "Sync policies detected new kube policy %v", kubePolicies[kn])
			kubernetesEvents = append(kubernetesEvents, Event{KubeEventAdded, kubePolicies[kn]})
		}
	}

	// Delete romana policies that don't have corresponding
	// kubernetes policy.
	// Ignore policies that don't have "kube." prefix in the name.
	for k, _ := range policies {
		if !strings.HasPrefix(policies[k].Name, "kube.") {
			log.Tracef(trace.Inside, "Sync policies skipping policy %s since it doesn't match the prefix `kube.`", policies[k].Name)
			continue
		}

		if !accountedRomanaPolicies[k] {
			log.Infof("Sync policies detected that romana policy %d is obsolete - scheduling for deletion", policies[k].ID)
			log.Tracef(trace.Inside, "Sync policies detected that romana policy %d is obsolete - scheduling for deletion", policies[k].ID)
			romanaPolicies = append(romanaPolicies, policies[k])
		}
	}

	return
}
Example #11
0
// SetEndpoint implements Firewall interface. It initializes
// endpoint dependend values of firewall.
func (i *IPTsaveFirewall) SetEndpoint(netif FirewallEndpoint) error {
	log.Infof("In SetEndpoint() with endpoint <iface=%s, ip=%s, mac=%s>", netif.GetName(), netif.GetIP(), netif.GetMac())

	var err error
	i.interfaceName = netif.GetName()

	i.u32filter, i.chainPrefix, err = prepareU32Rules(netif.GetIP(), i.networkConfig)
	if err != nil {
		return err
	}

	// Assemble firewall rules needed to divert traffic
	// to/from the endpoint.
	divertFilter := makeDivertRules(netif)
	log.Tracef(trace.Inside, "In SetEndpoint() after divertFilter with\n%s", divertFilter.RenderFooter())

	// compare list of divert rules and list of current rules
	// make a list of chains filled with divert rules that need
	// to be created to match current rules.
	backendFilter := i.CurrentState.TableByName("filter")
	newChains := iptsave.MergeTables(backendFilter, divertFilter)

	// schedule divert rules that don't exist yet for installation.
	newFilter := i.DesiredState.TableByName("filter")
	newFilter.Chains = append(newFilter.Chains, newChains...)

	log.Tracef(trace.Inside, "In SetEndpoint after merge\n%s", i.CurrentState.Render())

	return err
}
Example #12
0
// Init calls flag.Parse() and, for now, sets up the
// credentials.
func (cs *CliState) Init() error {
	cs.flagSet.Parse(os.Args[1:])
	config.SetConfigName(".romana") // name of config file (without extension)
	config.SetConfigType("yaml")
	config.AddConfigPath("$HOME") // adding home directory as first search path
	config.AutomaticEnv()         // read in environment variables that match

	// If a config file is found, read it in.
	err := config.ReadInConfig()
	if err != nil {
		switch err := err.(type) {
		case config.ConfigFileNotFoundError:
			// For now do nothing
		case *os.PathError:
			if err.Error() != "open : no such file or directory" {
				return err
			}
		default:
			return err
		}
	}
	log.Infof("Using config file: %s", config.ConfigFileUsed())
	err = cs.credential.Initialize()
	return err
}
Example #13
0
func (n notFoundHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
	// TODO answer with a 406 here?
	accept := request.Header.Get("accept")
	// Default to JSON.
	contentType := "application/json"
	if accept == "*/*" || accept == "" {
		// Force json if it can take anything.
		accept = "application/json"
	}

	format, err := negotiation.NegotiateAccept(accept, SupportedContentTypes)
	var marshaller Marshaller
	defaultMarshaller := ContentTypeMarshallers["application/json"]

	if err == nil {
		contentType = format.Value
		writer.Header().Set("Content-Type", contentType)
		marshaller = ContentTypeMarshallers[contentType]
	}
	// Error in negotiation or marshaller not found.
	if err != nil || marshaller == nil {
		// This should never happen... Just in case...
		log.Infof("No marshaler for [%s] found in %s, %s\n", contentType, ContentTypeMarshallers, ContentTypeMarshallers["application/json"])
		writer.WriteHeader(http.StatusUnsupportedMediaType)
		sct := SupportedContentTypesMessage
		dataOut, _ := defaultMarshaller.Marshal(sct)
		writer.Write(dataOut)
		return
	}
	dataOut, _ := marshaller.Marshal(NewError404("URI", request.RequestURI))
	writer.Write(dataOut)
	return
}
Example #14
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
}
Example #15
0
// ensureIPtablesChain checks if iptables chain in a desired state.
func (fw *IPtables) ensureIPtablesChain(chainName string, opType chainState) error {
	log.Infof("In ensureIPtablesChain(): %s %s", opType.String(), chainName)

	log.Tracef(trace.Inside, "In ensureIPtablesChain(): Testing chain ", chainName)
	exists := fw.isChainExistByName(chainName)
	log.Tracef(trace.Inside, "In ensureIPtablesChain(): Test for chain %s returned %b", chainName, exists)

	var iptablesAction string
	switch opType {
	case ensureChainExists:
		if exists {
			log.Tracef(trace.Inside, "In ensureIPtablesChain(): nothing to do for chain %s", chainName)
			return nil
		} else {
			iptablesAction = "-N"
		}

	case ensureChainAbsent:
		if exists {
			iptablesAction = "-D"
		} else {
			log.Tracef(trace.Inside, "In ensureIPtablesChain(): nothing to do for chain %s", chainName)
			return nil
		}
	}

	args := []string{iptablesAction, chainName}
	_, err := fw.os.Exec(iptablesCmd, args)
	return err
}
Example #16
0
// ListenAndServe is same as http.ListenAndServe except it returns
// the address that will be listened on (which is useful when using
// arbitrary ports).
// See https://github.com/golang/go/blob/master/src/net/http/server.go
func ListenAndServe(svr *http.Server) (*RestServiceInfo, error) {
	log.Infof("Entering ListenAndServe(%p)", svr)
	if svr.Addr == "" {
		svr.Addr = ":0"
	}
	ln, err := net.Listen("tcp", svr.Addr)
	if err != nil {
		return nil, err
	}
	realAddr := ln.Addr().String()
	channel := make(chan ServiceMessage)
	l := svr.ErrorLog
	if l == nil {
		l = clog.New(os.Stderr, "[negroni] ", 0)
	}
	go func() {
		channel <- Starting
		l.Printf("ListenAndServe(%p): listening on %s (asked for %s) with configuration %v, handler %v\n", svr, realAddr, svr.Addr, svr, svr.Handler)
		err := svr.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
		if err != nil {
			log.Criticalf("RestService: Fatal error %v", err)
			os.Exit(255)
		}
	}()
	return &RestServiceInfo{Address: realAddr, Channel: channel}, nil
}
Example #17
0
// If the path of request is common.AuthPath, this does nothing, as
// the request is for authentication in the first place. Otherwise,
// checks token from request. If the token is not valid, returns a
// 403 FORBIDDEN status.
func (am AuthMiddleware) ServeHTTP(writer http.ResponseWriter, request *http.Request, next http.HandlerFunc) {
	if request.URL.Path == AuthPath {
		// Let this one through, no token yet.
		next(writer, request)
		return
	}
	contentType := writer.Header().Get("Content-Type")
	marshaller := ContentTypeMarshallers[contentType]

	if am.PublicKey != nil {
		f := func(token *jwt.Token) (interface{}, error) {
			return am.PublicKey, nil
		}
		log.Infof("Parsing request for auth token\n")
		token, err := jwt.ParseFromRequest(request, f)

		if err != nil {
			writer.WriteHeader(http.StatusForbidden)
			httpErr := NewHttpError(http.StatusForbidden, err.Error())
			outData, _ := marshaller.Marshal(httpErr)
			writer.Write(outData)
			return
		}
		if !token.Valid {
			writer.WriteHeader(http.StatusForbidden)
			httpErr := NewHttpError(http.StatusForbidden, "Invalid token.")
			outData, _ := marshaller.Marshal(httpErr)
			writer.Write(outData)
			return
		}

		context.Set(request, ContextKeyRoles, token.Claims["roles"].([]string))
	}
	next(writer, request)
}
Example #18
0
// podDownHandler cleans up after pod deleted.
func (a *Agent) podDownHandler(input interface{}, ctx common.RestContext) (interface{}, error) {
	log.Trace(trace.Private, "Agent: Entering podDownHandler()")
	netReq := input.(*NetworkRequest)
	netif := netReq.NetIf

	// We need new firewall instance here to use its 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
	}

	// Spawn new thread to process the request
	log.Infof("Agent: Got request for pod teardown %v\n", netReq)

	return "OK", nil
}
Example #19
0
// write500 writes out a 500 error based on provided err
func write500(writer http.ResponseWriter, m Marshaller, err error) {
	writer.WriteHeader(http.StatusInternalServerError)
	httpErr := NewError500(err)
	// Should never error out - it's a struct we know.
	outData, _ := m.Marshal(httpErr)
	log.Infof("Made\n\t%+v\n\tfrom\n\t%+v\n\t%s", httpErr, err, string(outData))
	writer.Write(outData)
}
Example #20
0
// 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
}
Example #21
0
func (t *Translator) Init(client *common.RestClient, segmentLabelName, tenantLabelName string) {
	t.cacheMu = &sync.Mutex{}
	t.restClient = client
	err := t.updateCache()
	if err == nil {
		log.Infof("Translator cache updated - have %d tenant entries", len(t.tenantsCache))
	} else {
		log.Errorf("Translator cache update failed, %s", err)
	}
	t.segmentLabelName = segmentLabelName
	t.tenantLabelName = tenantLabelName
}
Example #22
0
File: store.go Project: romana/core
// DbToHttpError produces an appropriate HttpError given an error, if it can
// (for example, producing a 409 CONFLICT in case of a unique or primary key
// constraint violation). If it cannot, it returns the original error.
func DbToHttpError(err error) error {
	switch err := err.(type) {
	case sqlite3.Error:
		if err.Code == sqlite3.ErrConstraint {
			if err.ExtendedCode == sqlite3.ErrConstraintUnique || err.ExtendedCode == sqlite3.ErrConstraintPrimaryKey {
				log.Infof("Error: %s", err)
				return HttpError{StatusCode: http.StatusConflict}
			}
		} else if err.Code == sqlite3.ErrCantOpen {
			log.Infof("Cannot open database file.")
			return NewError500("Database error.")
		}
		log.Infof("DbToHttpError(): Unknown sqlite3 error: %d|%d|%s", err.Code, err.ExtendedCode, err.Error())
		return err
	case *mysql.MySQLError:
		if err.Number == MySQLUniqueConstraintErrorCode {
			log.Infof("Error: %s", err)
			return HttpError{StatusCode: http.StatusConflict}
		}
		log.Infof("DbToHttpError(): Unknown MySQL error: %d %s", err.Number, err.Message)
		return err
	default:
		log.Infof("DbToHttpError(): Unknown error: [%T] %+v", err, err)
		return err
	}
}
Example #23
0
File: store.go Project: romana/core
// createSchemaSqlite3 creates schema for a sqlite3 db
func createSchemaSqlite3(dbStore *DbStore, force bool) error {
	schemaName := dbStore.Config.Database
	log.Infof("Entering createSchemaSqlite3() with %s", schemaName)
	var err error
	if force {
		finfo, err := os.Stat(schemaName)
		exist := finfo != nil || os.IsExist(err)
		log.Infof("Before attempting to drop %s, exists: %t, stat: [%v] ... [%v]", schemaName, exist, finfo, err)
		if exist {
			err = os.Remove(schemaName)
			if err != nil {
				return err
			}
		}
	}
	err = dbStore.Connect()
	if err != nil {
		return err
	}

	entities := dbStore.ServiceStore.Entities()
	log.Infof("Creating tables for %v", entities)
	for _, entity := range entities {
		log.Infof("sqlite3: Creating table for %T", entity)
		db := dbStore.Db.CreateTable(entity)
		if db.Error != nil {
			return db.Error
		}
	}

	errs := dbStore.Db.GetErrors()
	log.Infof("sqlite3: Errors: %v", errs)
	err2 := MakeMultiError(errs)

	if err2 != nil {
		return err2
	}
	return dbStore.ServiceStore.CreateSchemaPostProcess()
}
Example #24
0
// makeRules extracts data from netif and initializes tenant/segment
// specific fields of IPtables struct.
func (fw *IPtables) makeRules(netif FirewallEndpoint) error {
	log.Infof("In makeRules() with %s", netif.GetName())

	var err error
	fw.u32filter, fw.chainPrefix, err = fw.prepareU32Rules(netif.GetIP())
	if err != nil {
		// TODO need personalized error here, or even panic
		return err
	}
	fw.interfaceName = netif.GetName()

	fw.chains = append(fw.chains, IPtablesChain{
		BaseChain:  "INPUT",
		Directions: []string{"i"},
		ChainName:  "ROMANA-INPUT",
	})
	fw.chains = append(fw.chains, IPtablesChain{
		BaseChain:  "OUTPUT",
		Directions: []string{"o"},
		ChainName:  "ROMANA-FORWARD-IN",
	})
	fw.chains = append(fw.chains, IPtablesChain{
		BaseChain:  "FORWARD",
		Directions: []string{"i"},
		ChainName:  "ROMANA-FORWARD-OUT",
	})
	fw.chains = append(fw.chains, IPtablesChain{
		BaseChain:  "FORWARD",
		Directions: []string{"o"},
		// Using ROMANA-FORWARD-IN second time to capture both
		// traffic from host to endpoint and
		// traffic from endpoint to another endpoint.
		ChainName: "ROMANA-FORWARD-IN",
	})

	log.Infof("In makeRules() created chains %v", fw.chains)
	return nil
}
Example #25
0
// setupHooks sets up before and after hooks for each service
func setupHooks(routes Routes, hooks []Hook) error {
	for i, hook := range hooks {
		if strings.ToLower(hook.When) != "before" && strings.ToLower(hook.When) != "after" {
			return errors.New(fmt.Sprintf("InitializeService(): Invalid value for when: %s", hook.When))
		}
		m := strings.ToUpper(hook.Method)
		if m != "POST" && m != "PUT" && m != "GET" && m != "DELETE" && m != "HEAD" {
			return errors.New(fmt.Sprintf("Invalid method: %s", m))
		}
		found := false
		for j, _ := range routes {
			r := &routes[j]
			if r.Pattern == hook.Pattern && strings.ToUpper(r.Method) == m {
				found = true
				r.Hook = &hooks[i]
				log.Infof("InitializeService(): [%d] Added hook to run %s %s %s %s", j, hook.Executable, hook.When, r.Method, r.Pattern)
				break
			}
		}

		for i, r := range routes {
			log.Infof("InitializeService(): Modified route[%d]: %s %s %v", i, r.Method, r.Pattern, r.Hook)
		}
		if !found {
			return errors.New(fmt.Sprintf("No route matching pattern %s and method %s found in %v", hook.Pattern, hook.Method, routes))
		}
		finfo, err := os.Stat(hook.Executable)
		if err != nil {
			return errors.New(fmt.Sprintf("Problem with specified executable %s: %v", hook.Executable, err))
		}

		if finfo.Mode().Perm()&0111 == 0 {
			return errors.New(fmt.Sprintf("%s is not an executable", hook.Executable))
		}
	}
	return nil

}
Example #26
0
// ReadConfig parses the configuration file provided and returns
// ReadConfig reads config from file to structure
func ReadConfig(fname string) (Config, error) {
	// Created new...
	config := &Config{}

	absFname, err := filepath.Abs(fname)
	if err != nil {
		return *config, err
	}
	if fname != absFname {
		log.Infof("ReadConfig(): Normalized %s to %s", fname, absFname)
		fname = absFname
	}
	yamlConfig := yamlConfig{}
	if fname != "" {
		data, err := ioutil.ReadFile(fname)
		if err != nil {
			return *config, err
		}
		err = yaml.Unmarshal(data, &yamlConfig)
		if err != nil {
			log.Infof("ReadConfig(): Error reading config: %v", err)
			return *config, err
		}
		serviceConfigs := yamlConfig.Services
		config.Services = make(map[string]ServiceConfig)
		// Now convert this to map for easier reading...
		for i := range serviceConfigs {
			c := serviceConfigs[i]
			api := Api{Host: c.Api.Host, Port: c.Api.Port, Hooks: c.Api.Hooks}
			cleanedConfig := cleanupMap(c.Config)
			commonConfig := CommonConfig{Api: &api, Credential: nil, PublicKey: nil}
			config.Services[c.Service] = ServiceConfig{Common: commonConfig, ServiceSpecific: cleanedConfig}
		}
		return *config, nil
	}
	return *config, errors.New("Empty filename.")
}
Example #27
0
// podUpHandler handles HTTP requests for endpoints provisioning.
func (a *Agent) podUpHandler(input interface{}, ctx common.RestContext) (interface{}, error) {
	log.Trace(trace.Private, "Agent: Entering podUpHandler()")
	netReq := input.(*NetworkRequest)

	log.Infof("Agent: Got request for network configuration: %v\n", netReq)
	// Spawn new thread to process the request

	// TODO don't know if fork-bombs are possible in go but if they are this
	// need to be refactored as buffered channel with fixed pool of workers
	go a.podUpHandlerAsync(*netReq)

	// TODO I wonder if this should actually return something like a
	// link to a status of this request which will later get updated
	// with success or failure -- Greg.
	return "OK", nil
}
Example #28
0
// NewRouter creates router for a new service.
func newRouter(routes []Route) *mux.Router {
	router := mux.NewRouter().StrictSlash(true)

	router.NotFoundHandler = notFoundHandler{}
	for _, route := range routes {
		handler := route.Handler
		if route.Hook != nil {
			log.Infof("Calling wrapHandler with %s %s %s", route.Method, route.Pattern, route.Hook.Executable)
		}
		wrappedHandler := wrapHandler(handler, route)
		router.
			Methods(route.Method).
			Path(route.Pattern).
			Handler(wrappedHandler)
	}
	return router
}
Example #29
0
// vmUpHandler handles HTTP requests for endpoints provisioning.
// Currently tested with Romana ML2 driver.
func (a *Agent) vmUpHandler(input interface{}, ctx common.RestContext) (interface{}, error) {
	// Parse out NetIf form the request
	netif := input.(*NetIf)

	log.Infof("Agent: Got interface: Name %s, IP %s Mac %s\n", netif.Name, netif.IP, netif.Mac)

	// Spawn new thread to process the request

	// TODO don't know if fork-bombs are possible in go but if they are this
	// need to be refactored as buffered channel with fixed pool of workers
	go a.vmUpHandlerAsync(*netif)

	// TODO I wonder if this should actually return something like a
	// link to a status of this request which will later get updated
	// with success or failure -- Greg.
	return "OK", nil
}
Example #30
0
// 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
}