func (d *Daemon) checkEgressAccess(e *endpoint.Endpoint, opts option.OptionMap, dstID uint32, opt string) { var err error ctx := policy.SearchContext{ From: e.Consumable.LabelList, } d.conf.OptsMU.RLock() if d.conf.Opts.IsEnabled(OptionPolicyTracing) { ctx.Trace = policy.TRACE_ENABLED } d.conf.OptsMU.RUnlock() ctx.To, err = d.GetCachedLabelList(dstID) if err != nil { log.Warningf("Unable to get label list for ID %d, access for endpoint may be restricted\n", dstID) return } switch d.policyCanConsume(&ctx) { case policy.ACCEPT, policy.ALWAYS_ACCEPT: opts[opt] = true case policy.DENY: opts[opt] = false } }
// PolicyCanConsume calculates if the ctx allows the consumer to be consumed. This public // function returns a SearchContextReply with the consumable decision and the tracing log // if ctx.Trace was set. func (d *Daemon) PolicyCanConsume(ctx *policy.SearchContext) (*policy.SearchContextReply, error) { buffer := new(bytes.Buffer) if ctx.Trace != policy.TRACE_DISABLED { ctx.Logging = logging.NewLogBackend(buffer, "", 0) } scr := policy.SearchContextReply{} d.policyMU.RLock() scr.Decision = d.policyCanConsume(ctx) d.policyMU.RUnlock() if ctx.Trace != policy.TRACE_DISABLED { scr.Logging = buffer.Bytes() } return &scr, nil }
// Must be called with endpointsMU held func (d *Daemon) regenerateConsumable(e *endpoint.Endpoint) error { c := e.Consumable // Containers without a security label are not accessible if c.ID == 0 { log.Fatalf("Impossible: SecLabel == 0 when generating endpoint consumers") return nil } // Skip if policy for this consumable is already valid if c.Iteration == d.cacheIteration { log.Debugf("Policy for %d is already calculated, reusing...", c.ID) return nil } maxID, err := d.GetMaxLabelID() if err != nil { return err } ctx := policy.SearchContext{ To: c.LabelList, } d.conf.OptsMU.RLock() if d.conf.Opts.IsEnabled(OptionPolicyTracing) { ctx.Trace = policy.TRACE_ENABLED } d.conf.OptsMU.RUnlock() // Mark all entries unused by denying them for k := range c.Consumers { c.Consumers[k].DeletionMark = true } d.policyMU.RLock() // Check access from reserved consumables first for _, id := range d.reservedConsumables { if err := d.evaluateConsumerSource(e, &ctx, id.ID); err != nil { // This should never really happen // FIXME: clear policy because it is inconsistent break } } // Iterate over all possible assigned search contexts idx := common.FirstFreeLabelID for idx < maxID { if err := d.evaluateConsumerSource(e, &ctx, idx); err != nil { // FIXME: clear policy because it is inconsistent break } idx++ } d.policyMU.RUnlock() // Garbage collect all unused entries for _, val := range c.Consumers { if val.DeletionMark { val.DeletionMark = false c.BanConsumer(val.ID) } } // Result is valid until cache iteration advances c.Iteration = d.cacheIteration log.Debugf("New policy (iteration %d) for consumable %d: %+v\n", c.Iteration, c.ID, c.Consumers) return nil }