github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/tao/cached_guard.go (about)

     1  // Copyright (c) 2015, Google Inc.  All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package tao
    16  
    17  import (
    18  	"errors"
    19  	"fmt"
    20  	"time"
    21  
    22  	"github.com/jlmucb/cloudproxy/go/tao/auth"
    23  )
    24  
    25  // CachedGuard implements the Guard interface on behalf of a remote guard.
    26  // When the interface is queried, the cached guard checks if it has an
    27  // up-to-date version of the policy. If it doesn't, it creates a connection
    28  // to a TaoCA, requests the policy rules, and instantiates a new guard.
    29  type CachedGuard struct {
    30  	guardType CachedGuardType
    31  	guard     Guard
    32  
    33  	// Details of TaoCA.
    34  	network string // e.g. "tcp"
    35  	address string // e.g. "localhost:8124"
    36  
    37  	// TODO(cjpatton) use time.Duration instead of int64.
    38  	timeToLive  int64 // Number of seconds until guard expires
    39  	timeUpdated int64 // Timestamp of last update.
    40  
    41  	// Public policy key. (The TaoCA should sign with the private policy key.)
    42  	verifier *Verifier
    43  }
    44  
    45  // CachedGuardType specifies the type of guard being cached.
    46  type CachedGuardType int
    47  
    48  // There should be a type for all non-trivial gaurds.
    49  const (
    50  	Datalog CachedGuardType = 1 << iota
    51  	ACLs
    52  )
    53  
    54  var errCachedNotImplemented = errors.New("CachedGuard: not implemented.")
    55  var errCachedGuardSave = errors.New("CachedGuard: saving cached policy is not allowed.")
    56  var errCachedGuardReload = errors.New("CachedGuard: failed to update policy.")
    57  
    58  // NewCachedGuard returns a new CachedGuard.
    59  func NewCachedGuard(vfy *Verifier, t CachedGuardType, network, addr string, ttl int64) *CachedGuard {
    60  	return &CachedGuard{
    61  		guardType:  t,
    62  		network:    network,
    63  		address:    addr,
    64  		verifier:   vfy,
    65  		timeToLive: ttl,
    66  	}
    67  }
    68  
    69  // IsExpired checks if the cached policy is out of date.
    70  func (cg *CachedGuard) IsExpired() bool {
    71  	return (time.Now().Unix() - cg.timeUpdated) > cg.timeToLive
    72  }
    73  
    74  // Reload requests the policy from the remote TaoCA and instantiates a
    75  // new guard.
    76  func (cg *CachedGuard) Reload() error {
    77  	switch cg.guardType {
    78  	case Datalog:
    79  		datalogGuard := NewDatalogGuard(cg.verifier)
    80  		db, err := RequestDatalogRules(cg.network, cg.address, cg.verifier)
    81  		if err != nil {
    82  			return err
    83  		}
    84  		datalogGuard.db = *db
    85  		for _, marshaledForm := range db.Rules {
    86  			f, _ := auth.UnmarshalForm(marshaledForm)
    87  			rule, _, err := datalogGuard.findRule(f)
    88  			if err != nil {
    89  				return err
    90  			}
    91  			datalogGuard.dl.Assert(rule)
    92  		}
    93  		cg.guard = datalogGuard
    94  	case ACLs: // TODO(cjpatton)
    95  		return errors.New("CacheGuard: ACL set reload not implemented")
    96  	}
    97  	cg.timeUpdated = time.Now().Unix()
    98  	return nil
    99  }
   100  
   101  // Subprincipal returns a Subprin for the guard.
   102  func (cg *CachedGuard) Subprincipal() auth.SubPrin {
   103  	// TODO(cjpatton) should be "CachedGuard(Datalog).DatalogGuard(...)"
   104  	var guardType string
   105  	switch cg.guardType {
   106  	case Datalog:
   107  		guardType = "Datalog"
   108  	case ACLs:
   109  		guardType = "ACLs"
   110  	}
   111  	e := auth.PrinExt{Name: "CachedGuard",
   112  		Arg: []auth.Term{auth.Str(guardType)}}
   113  	return auth.SubPrin{e}
   114  }
   115  
   116  // Save stores the cached policy to disk.
   117  func (cg *CachedGuard) Save(key *Signer) error {
   118  	// TODO(cjpatton) Save cached policy to disk (just call guard.Save()).
   119  	// Add rules file to domain config. We will need a ReloadFromDisk()
   120  	// method as well.
   121  	return nil
   122  }
   123  
   124  // Authorize is not allowed for cached guards, since it doesn't have the
   125  // private policy key.
   126  func (cg *CachedGuard) Authorize(name auth.Prin, op string, args []string) error {
   127  	return errCachedNotImplemented
   128  }
   129  
   130  // Retract is not allowed for cached guards.
   131  func (cg *CachedGuard) Retract(name auth.Prin, op string, args []string) error {
   132  	return errCachedNotImplemented
   133  }
   134  
   135  // IsAuthorized checks if the principal `name` is authorized to perform `op`
   136  // on `args`.
   137  func (cg *CachedGuard) IsAuthorized(name auth.Prin, op string, args []string) bool {
   138  	if cg.guard == nil || cg.IsExpired() {
   139  		if err := cg.Reload(); err != nil {
   140  			return false
   141  		}
   142  	}
   143  	return cg.guard.IsAuthorized(name, op, args)
   144  }
   145  
   146  // AddRule is not allowed for cached guards.
   147  func (cg *CachedGuard) AddRule(rule string) error {
   148  	if cg.guard == nil || cg.IsExpired() {
   149  		if err := cg.Reload(); err != nil {
   150  			return err
   151  		}
   152  	}
   153  	return cg.guard.AddRule(rule)
   154  }
   155  
   156  // RetractRule is not allowed for cached guards.
   157  func (cg *CachedGuard) RetractRule(rule string) error {
   158  	return errCachedNotImplemented
   159  }
   160  
   161  // Clear deletes the guard. This will cause a Reload() the next time the guard
   162  // is queried.
   163  func (cg *CachedGuard) Clear() error {
   164  	cg.guard = nil
   165  	return nil
   166  }
   167  
   168  // Query the policy.
   169  func (cg *CachedGuard) Query(query string) (bool, error) {
   170  	if cg.guard == nil || cg.IsExpired() {
   171  		if err := cg.Reload(); err != nil {
   172  			return false, nil
   173  		}
   174  	}
   175  	return cg.guard.Query(query)
   176  }
   177  
   178  // RuleCount returns the number of rules in the policy.
   179  func (cg *CachedGuard) RuleCount() int {
   180  	if cg.guard == nil || cg.IsExpired() {
   181  		if err := cg.Reload(); err != nil {
   182  			return 0
   183  		}
   184  	}
   185  	return cg.guard.RuleCount()
   186  }
   187  
   188  // GetRule returns a string representation of the i-th rule in the policy.
   189  func (cg *CachedGuard) GetRule(i int) string {
   190  	if cg.guard == nil || cg.IsExpired() {
   191  		if err := cg.Reload(); err != nil {
   192  			return ""
   193  		}
   194  	}
   195  	return cg.guard.GetRule(i)
   196  }
   197  
   198  // RuleDebugString returns a verbose string representation of the i-th rule
   199  // in the policy useful for debugging.
   200  func (cg *CachedGuard) RuleDebugString(i int) string {
   201  	if cg.guard == nil || cg.IsExpired() {
   202  		if err := cg.Reload(); err != nil {
   203  			return ""
   204  		}
   205  	}
   206  	return cg.guard.RuleDebugString(i)
   207  }
   208  
   209  // String returns a string representation of the guard.
   210  func (cg *CachedGuard) String() string {
   211  	var s string
   212  	if cg.guard == nil {
   213  		switch cg.guardType {
   214  		case Datalog:
   215  			s = fmt.Sprintf("undefined Datalog, %s", cg.address)
   216  		case ACLs:
   217  			s = fmt.Sprintf("undefined ACLs, %s", cg.address)
   218  		}
   219  	} else {
   220  		s = "\n" + cg.guard.String() + "\n"
   221  	}
   222  	return "CachedGuard{" + s + "}"
   223  }