func (c *ConsulClient) GASNewSecLabelID(basePath string, baseID uint32, secCtxLabels *labels.SecCtxLabel) error { setID2Label := func(lockPair *consulAPI.KVPair) error { defer c.KV().Release(lockPair, nil) secCtxLabels.ID = baseID keyPath := path.Join(basePath, strconv.FormatUint(uint64(secCtxLabels.ID), 10)) if err := c.SetValue(keyPath, secCtxLabels); err != nil { return err } return c.setMaxLabelID(baseID + 1) } session, _, err := c.Session().CreateNoChecks(nil, nil) if err != nil { return err } beginning := baseID for { log.Debugf("Trying to acquire a new free ID %d", baseID) keyPath := path.Join(basePath, strconv.FormatUint(uint64(baseID), 10)) lockPair := &consulAPI.KVPair{Key: GetLockPath(keyPath), Session: session} acq, _, err := c.KV().Acquire(lockPair, nil) if err != nil { return err } if acq { lblKey, _, err := c.KV().Get(keyPath, nil) if err != nil { c.KV().Release(lockPair, nil) return err } if lblKey == nil { return setID2Label(lockPair) } var consulLabels labels.SecCtxLabel if err := json.Unmarshal(lblKey.Value, &consulLabels); err != nil { c.KV().Release(lockPair, nil) return err } if consulLabels.RefCount() == 0 { log.Infof("Recycling ID %d", baseID) return setID2Label(lockPair) } c.KV().Release(lockPair, nil) } baseID++ if baseID > common.MaxSetOfLabels { baseID = common.FirstFreeLabelID } if beginning == baseID { return fmt.Errorf("reached maximum set of labels available.") } } }
// GASNewSecLabelID gets the next available LabelID and sets it in secCtxLabels. After // assigning the LabelID to secCtxLabels it sets the LabelID + 1 in // common.LastFreeLabelIDKeyPath path. func (e *EtcdClient) GASNewSecLabelID(basePath string, baseID uint32, secCtxLabels *labels.SecCtxLabel) error { setID2Label := func(id uint32) error { secCtxLabels.ID = id keyPath := path.Join(basePath, strconv.FormatUint(uint64(secCtxLabels.ID), 10)) if err := e.SetValue(keyPath, secCtxLabels); err != nil { return err } return e.setMaxLabelID(id + 1) } acquireFreeID := func(firstID uint32, incID *uint32) (bool, error) { log.Debugf("Trying to acquire a new free ID %d", *incID) keyPath := path.Join(basePath, strconv.FormatUint(uint64(*incID), 10)) locker, err := e.LockPath(GetLockPath(keyPath)) if err != nil { return false, err } defer locker.Unlock() value, err := e.GetValue(keyPath) if err != nil { return false, err } if value == nil { return false, setID2Label(*incID) } var consulLabels labels.SecCtxLabel if err := json.Unmarshal(value, &consulLabels); err != nil { return false, err } if consulLabels.RefCount() == 0 { log.Infof("Recycling ID %d", *incID) return false, setID2Label(*incID) } *incID++ if *incID > common.MaxSetOfLabels { *incID = common.FirstFreeLabelID } if firstID == *incID { return false, fmt.Errorf("reached maximum set of labels available.") } return true, nil } beginning := baseID for { retry, err := acquireFreeID(beginning, &baseID) if err != nil { return err } else if !retry { return nil } } }
// GetLabelsBySHA256 returns the SecCtxLabels that have the given SHA256SUM. func (d *Daemon) GetLabelsBySHA256(sha256sum string) (*labels.SecCtxLabel, error) { path := path.Join(common.LabelsKeyPath, sha256sum) rmsg, err := d.kvClient.GetValue(path) if err != nil { return nil, err } if rmsg == nil { return nil, nil } var secCtxLabels labels.SecCtxLabel if err := json.Unmarshal(rmsg, &secCtxLabels); err != nil { return nil, err } if secCtxLabels.RefCount() == 0 { return nil, nil } return &secCtxLabels, nil }
// GetLabels returns the SecCtxLabels that belongs to the given id. func (d *Daemon) GetLabels(id uint32) (*labels.SecCtxLabel, error) { if id > 0 && id < common.FirstFreeLabelID { key := labels.ReservedID(id).String() if key == "" { return nil, nil } lbl := labels.NewLabel( key, "", common.ReservedLabelSource, ) secLbl := labels.NewSecCtxLabel() secLbl.AddOrUpdateContainer(lbl.String()) secLbl.ID = id secLbl.Labels = labels.Labels{ common.ReservedLabelSource: lbl, } return secLbl, nil } strID := strconv.FormatUint(uint64(id), 10) rmsg, err := d.kvClient.GetValue(path.Join(common.LabelIDKeyPath, strID)) if err != nil { return nil, err } if rmsg == nil { return nil, nil } var secCtxLabels labels.SecCtxLabel if err := json.Unmarshal(rmsg, &secCtxLabels); err != nil { return nil, err } if secCtxLabels.RefCount() == 0 { return nil, nil } return &secCtxLabels, nil }
// DeleteLabelsBySHA256 deletes the SecCtxLabels that belong to the labels' sha256Sum. func (d *Daemon) DeleteLabelsBySHA256(sha256Sum string, contID string) error { if sha256Sum == "" { return nil } lblPath := path.Join(common.LabelsKeyPath, sha256Sum) // Lock that sha256Sum lockKey, err := d.kvClient.LockPath(lblPath) if err != nil { return err } defer lockKey.Unlock() // After lock complete, get label's path rmsg, err := d.kvClient.GetValue(lblPath) if err != nil { return err } if rmsg == nil { return nil } var dbSecCtxLbls labels.SecCtxLabel if err := json.Unmarshal(rmsg, &dbSecCtxLbls); err != nil { return err } dbSecCtxLbls.DelContainer(contID) // update the value in the kvstore if err := d.updateSecLabelIDRef(dbSecCtxLbls); err != nil { return err } if dbSecCtxLbls.RefCount() == 0 { d.DeleteUINode(dbSecCtxLbls.ID) } else { d.AddOrUpdateUINode(dbSecCtxLbls.ID, dbSecCtxLbls.Labels.ToSlice(), dbSecCtxLbls.RefCount()) } log.Debugf("Decremented label %d ref-count to %d\n", dbSecCtxLbls.ID, dbSecCtxLbls.RefCount()) return d.kvClient.SetValue(lblPath, dbSecCtxLbls) }