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 }