func (d *Daemon) policyAdd(path string, node *policy.Node) error { var ( currNode, parentNode *policy.Node err error ) if node.Name == "" { path, node.Name = policy.SplitNodePath(path) } else if strings.Contains(node.Name, ".") && node.Name != common.GlobalLabelPrefix { path, node.Name = policy.SplitNodePath(path + "." + node.Name) } currNode, parentNode, err = d.findNode(path) if err != nil { return err } log.Debugf("Policy currNode %+v, parentNode %+v", currNode, parentNode) // eg. path = io.cilium.lizards.foo.db and io.cilium.lizards doesn't exist if (currNode == nil && parentNode == nil) || // eg. path = io.cilium.lizards.foo and io.cilium.lizards.foo doesn't exist (currNode == nil && parentNode != nil) { pn := policy.NewNode("", nil) if err := d.policyAdd(path, pn); err != nil { return err } currNode, parentNode, err = d.findNode(path) if err != nil { return err } log.Debugf("Policy currNode %+v, parentNode %+v", currNode, parentNode) } // eg. path = io.cilium if currNode != nil && parentNode == nil { if currNode.Name == node.Name { node.Path() if err := currNode.Merge(node); err != nil { return err } } else { if err := currNode.AddChild(node.Name, node); err != nil { return err } } } else if currNode != nil && parentNode != nil { // eg. path = io.cilium.lizards.db exists if err := currNode.AddChild(node.Name, node); err != nil { return err } } return nil }
func (d *Daemon) PolicyAdd(path string, node *policy.Node) error { log.Debugf("Policy Add Request: %s %+v", path, node) if !strings.HasPrefix(path, common.GlobalLabelPrefix) { return fmt.Errorf("the given path %q doesn't have the prefix %q", path, common.GlobalLabelPrefix) } d.policyMU.Lock() if err := d.policyAdd(path, node); err != nil { d.policyMU.Unlock() return err } if err := node.ResolveTree(); err != nil { d.policyMU.Unlock() return err } d.policyMU.Unlock() d.triggerPolicyUpdates([]uint32{}) return nil }
func (router *Router) policyAddForm(w http.ResponseWriter, r *http.Request) { const _4MBMemory = 4 << 20 err := r.ParseMultipartForm(_4MBMemory) if err != nil { processServerError(w, r, err) return } file, _, err := r.FormFile("policy-input-file") if err != nil { processServerError(w, r, err) return } var pn policy.Node if err := json.NewDecoder(file).Decode(&pn); err != nil { processServerError(w, r, err) return } if err := router.daemon.PolicyAdd(pn.Path(), &pn); err != nil { processServerError(w, r, err) return } w.WriteHeader(http.StatusCreated) }
func loadPolicy(name string) (*policy.Node, error) { log.Debugf("Entering directory %s...", name) if name == "-" { return loadPolicyFile(name) } if fi, err := os.Stat(name); err != nil { return nil, err } else if fi.Mode().IsRegular() { return loadPolicyFile(name) } else if !fi.Mode().IsDir() { return nil, fmt.Errorf("Error: %s is not a file or a directory", name) } files, err := ioutil.ReadDir(name) if err != nil { return nil, err } var node *policy.Node // process all files first for _, f := range files { if f.IsDir() || ignoredFile(path.Base(f.Name())) { continue } if p, err := loadPolicyFile(filepath.Join(name, f.Name())); err != nil { return nil, err } else { if node != nil { if err := node.Merge(p); err != nil { return nil, fmt.Errorf("Error: %s: %s", f.Name(), err) } } else { node = p } } } // recursive search for _, f := range files { if f.IsDir() { if ignoredFile(path.Base(f.Name())) { continue } subpath := filepath.Join(name, f.Name()) if p, err := loadPolicy(subpath); err != nil { return nil, err } else { if p.Name == "" { return nil, fmt.Errorf("Policy node import from %s did not derive a name", subpath) } node.AddChild(p.Name, p) } } } log.Debugf("Leaving directory %s...", name) return node, nil }
func (ds *DaemonSuite) TestUpdateConsumerMap(c *C) { lblProd := labels.NewLabel("io.cilium.Prod", "", common.CiliumLabelSource) lblQA := labels.NewLabel("io.cilium.QA", "", common.CiliumLabelSource) lblFoo := labels.NewLabel("io.cilium.foo", "", common.CiliumLabelSource) lblBar := labels.NewLabel("io.cilium.bar", "", common.CiliumLabelSource) lblJoe := labels.NewLabel("io.cilium.user", "joe", common.CiliumLabelSource) lblPete := labels.NewLabel("io.cilium.user", "pete", common.CiliumLabelSource) rootNode := policy.Node{ Name: common.GlobalLabelPrefix, Rules: []policy.PolicyRule{ &policy.PolicyRuleConsumers{ Coverage: []labels.Label{*lblBar}, Allow: []policy.AllowRule{ // always-allow: user=joe {Action: policy.ALWAYS_ACCEPT, Label: *lblJoe}, // allow: user=pete {Action: policy.ACCEPT, Label: *lblPete}, }, }, &policy.PolicyRuleRequires{ // coverage qa, requires qa Coverage: []labels.Label{*lblQA}, Requires: []labels.Label{*lblQA}, }, &policy.PolicyRuleRequires{ // coverage prod, requires: prod Coverage: []labels.Label{*lblProd}, Requires: []labels.Label{*lblProd}, }, }, Children: map[string]*policy.Node{ "foo": {}, "bar": { Rules: []policy.PolicyRule{ &policy.PolicyRuleConsumers{ Allow: []policy.AllowRule{ { // allow: foo Action: policy.ACCEPT, Label: *lblFoo, }, {Action: policy.DENY, Label: *lblJoe}, {Action: policy.DENY, Label: *lblPete}, }, }, }, }, }, } c.Assert(rootNode.ResolveTree(), Equals, nil) err := ds.d.PolicyAdd("io.cilium", &rootNode) c.Assert(err, Equals, nil) qaBarLbls := labels.Labels{lblBar.Key: lblBar, lblQA.Key: lblQA} qaBarSecLblsCtx, _, err := ds.d.PutLabels(qaBarLbls, "cc08ff400e355f736dce1c291a6a4007ab9f2d56d42e1f3630ba87b861d45307") c.Assert(err, Equals, nil) prodBarLbls := labels.Labels{lblBar.Key: lblBar, lblProd.Key: lblProd} prodBarSecLblsCtx, _, err := ds.d.PutLabels(prodBarLbls, "cc08ff400e355f736dce1c291a6a4007ab9f2d56d42e1f3630ba87b861d45307") c.Assert(err, Equals, nil) qaFooLbls := labels.Labels{lblFoo.Key: lblFoo, lblQA.Key: lblQA} qaFooSecLblsCtx, _, err := ds.d.PutLabels(qaFooLbls, "cc08ff400e355f736dce1c291a6a4007ab9f2d56d42e1f3630ba87b861d45307") c.Assert(err, Equals, nil) prodFooLbls := labels.Labels{lblFoo.Key: lblFoo, lblProd.Key: lblProd} prodFooSecLblsCtx, _, err := ds.d.PutLabels(prodFooLbls, "cc08ff400e355f736dce1c291a6a4007ab9f2d56d42e1f3630ba87b861d45307") c.Assert(err, Equals, nil) prodFooJoeLbls := labels.Labels{lblFoo.Key: lblFoo, lblProd.Key: lblProd, lblJoe.Key: lblJoe} prodFooJoeSecLblsCtx, _, err := ds.d.PutLabels(prodFooJoeLbls, "cc08ff400e355f736dce1c291a6a4007ab9f2d56d42e1f3630ba87b861d45307") c.Assert(err, Equals, nil) e := endpoint.Endpoint{ ID: 1, IfName: "dummy1", IPv6: IPv6Addr, IPv4: IPv4Addr, LXCMAC: HardAddr, NodeMAC: HardAddr, } e.Opts = option.NewBoolOptions(&DaemonOptionLibrary) e.Opts.SetIfUnset(endpoint.OptionLearnTraffic, false) err = os.Mkdir("1", 755) c.Assert(err, IsNil) defer func() { err = os.RemoveAll("1/geneve_opts.cfg") err = os.RemoveAll("1/lxc_config.h") time.Sleep(1 * time.Second) err = os.RemoveAll("1") err = os.RemoveAll("1_backup") }() e.SetSecLabel(qaBarSecLblsCtx) err = ds.d.regenerateEndpoint(&e) c.Assert(err, Equals, nil) c.Assert(e.Allows(qaBarSecLblsCtx.ID), Equals, false) c.Assert(e.Allows(prodBarSecLblsCtx.ID), Equals, false) c.Assert(e.Allows(qaFooSecLblsCtx.ID), Equals, true) c.Assert(e.Allows(prodFooSecLblsCtx.ID), Equals, false) c.Assert(e.Allows(prodFooJoeSecLblsCtx.ID), Equals, true) e = endpoint.Endpoint{ ID: 1, IfName: "dummy1", IPv6: IPv6Addr, IPv4: IPv4Addr, LXCMAC: HardAddr, NodeMAC: HardAddr, } e.Opts = option.NewBoolOptions(&DaemonOptionLibrary) e.Opts.SetIfUnset(endpoint.OptionLearnTraffic, false) e.SetSecLabel(prodBarSecLblsCtx) err = ds.d.regenerateEndpoint(&e) c.Assert(err, Equals, nil) c.Assert(e.Allows(0), Equals, false) c.Assert(e.Allows(qaBarSecLblsCtx.ID), Equals, false) c.Assert(e.Allows(prodBarSecLblsCtx.ID), Equals, false) c.Assert(e.Allows(qaFooSecLblsCtx.ID), Equals, false) c.Assert(e.Allows(prodFooSecLblsCtx.ID), Equals, true) c.Assert(e.Allows(prodFooJoeSecLblsCtx.ID), Equals, true) err = ds.d.PolicyDelete("io.cilium") c.Assert(err, Equals, nil) }