github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/tao/cached_guard_test.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 "crypto/x509/pkix" 19 "fmt" 20 "net" 21 "os" 22 "path" 23 "testing" 24 25 "github.com/golang/protobuf/proto" 26 "github.com/jlmucb/cloudproxy/go/tao/auth" 27 ) 28 29 // TODO(cjpatton) Add a test case to show it fails properly when the rules 30 // can't be loaded, e.g. when there is no network config. 31 // TODO(cjaptton) Use t.Error() to log errors instead of t.Fatal() in the case 32 // that a recoverable error occured. 33 // TODO(cjpatton) Write request to poll every few seconds until a connection is 34 // established, 35 // TODO(cjpatton) Modify CreatePublicCachedDomain() to accept either (network,addr) or a 36 // net.Conn. Modify this test to use net.Pipe instead of the loopback interface here. 37 38 var password = make([]byte, 32) 39 var prin = auth.NewKeyPrin([]byte("Alice")) 40 41 func makeTestDomains(configDir, network, addr string, ttl int64) (policy *Domain, public *Domain, err error) { 42 password[0] = 1 43 44 // Create a domain with a Datalog guard and policy keys. 45 var policyDomainConfig DomainConfig 46 policyDomainConfig.SetDefaults() 47 policyDomainConfig.DomainInfo.GuardType = proto.String("Datalog") 48 policyDomainConfig.DatalogGuardInfo = &DatalogGuardDetails{ 49 SignedRulesPath: proto.String("rules"), 50 } 51 configPath := path.Join(configDir, "tao.config") 52 53 policy, err = CreateDomain(policyDomainConfig, configPath, password) 54 if err != nil { 55 return nil, nil, err 56 } 57 58 // Add some bogus rules. 59 err = policy.Guard.AddRule( 60 `(forall P: forall F: IsFood(F) and IsPerson(P) implies Authorized(P, "eat", F))`) 61 if err != nil { 62 return nil, nil, err 63 } 64 if err = policy.Guard.AddRule(fmt.Sprintf(`IsPerson(%v)`, prin)); err != nil { 65 return nil, nil, err 66 } 67 if err = policy.Guard.AddRule(`IsFood("sandwich")`); err != nil { 68 return nil, nil, err 69 } 70 71 // Create a public domain with a Cached Datalog guard. 72 public, err = policy.CreatePublicCachedDomain(network, addr, ttl) 73 if err != nil { 74 return nil, nil, err 75 } 76 77 return 78 } 79 80 func TestCachingDatalogLoad(t *testing.T) { 81 network := "tcp" 82 addr := "localhost:0" 83 ttl := int64(1) 84 configDir := "/tmp/domain_test" 85 86 ch := make(chan bool) 87 cal, err := net.Listen(network, addr) 88 if err != nil { 89 t.Fatal(err) 90 } 91 defer cal.Close() 92 addr = cal.Addr().String() 93 94 policy, _, err := makeTestDomains(configDir, network, addr, ttl) 95 if err != nil { 96 t.Fatal(err) 97 } 98 defer os.RemoveAll(configDir) 99 defer os.RemoveAll(configDir + ".pub") 100 public, err := LoadDomain(path.Join(configDir+".pub", "tao.config"), nil) 101 if err != nil { 102 t.Fatal(err) 103 } 104 105 go runTCCA(t, cal, policy.Keys, policy.Guard, ch) 106 107 // This should cause an implicit reload. If the request to the TaoCA fails, 108 // IsAuthorized() will return false and not propagate an error. 109 if public.Guard.IsAuthorized(prin, "eat", []string{"sandwich"}) == false { 110 t.Fatal("IsAuthorized() failed, good rule should have been authorized") 111 } 112 <-ch 113 } 114 115 func TestCachingDatalogReload(t *testing.T) { 116 117 network := "tcp" 118 addr := "localhost:0" 119 ttl := int64(10) 120 121 // Run the TaoCA. This handles one request and then exits. 122 ch := make(chan bool) 123 cal, err := net.Listen(network, addr) 124 if err != nil { 125 t.Fatal(err) 126 } 127 defer cal.Close() 128 addr = cal.Addr().String() 129 130 configDir := "/tmp/domain_test" 131 policyDomain, publicDomain, err := makeTestDomains(configDir, network, addr, ttl) 132 if err != nil { 133 t.Fatal(err) 134 } 135 defer os.RemoveAll(configDir) 136 defer os.RemoveAll(configDir + ".pub") 137 138 // Sanity check. 139 if policyDomain.Guard.IsAuthorized(prin, "eat", []string{"sandwich"}) == false { 140 t.Fatal("Policy guard IsAuthorized() failed, good rule should have been authorized") 141 } 142 143 go runTCCA(t, cal, policyDomain.Keys, policyDomain.Guard, ch) 144 145 // Explicitly call Reload(), generating a policy request. 146 if err = publicDomain.Guard.(*CachedGuard).Reload(); err != nil { 147 t.Fatal(err) 148 } 149 150 // Print rules. 151 ct := publicDomain.Guard.RuleCount() 152 for i := 0; i < ct; i++ { 153 t.Logf("rule %d: %s", i, publicDomain.Guard.GetRule(i)) 154 } 155 <-ch 156 157 // Force Reload() by clearing the guard. 158 publicDomain.Guard.Clear() 159 go runTCCA(t, cal, policyDomain.Keys, policyDomain.Guard, ch) 160 161 // This should cause an implicit reload. If the request to the TaoCA fails, 162 // IsAuthorized() will return false and not propagate an error. 163 if publicDomain.Guard.IsAuthorized(prin, "eat", []string{"sandwich"}) == false { 164 t.Fatal("IsAuthorized() failed, good rule should have been authorized") 165 } 166 <-ch 167 168 // Simulate time-to-live running out. 169 publicDomain.Guard.(*CachedGuard).timeUpdated -= ttl + 1 170 go runTCCA(t, cal, policyDomain.Keys, policyDomain.Guard, ch) 171 172 if publicDomain.Guard.IsAuthorized(prin, "eat", []string{"salad"}) == true { 173 t.Fatal("IsAuthorized() succeeded, bad rule should have been denied") 174 } 175 <-ch 176 } 177 178 // Test that a client can correctly verify that the server is allowed to 179 // execute according to the policy. The policy is set up and the policy 180 // key is used to attest to the identity of the server. The attestation 181 // includes an endorsement of the service itself. The client verifies the 182 // endorsement and adds the predicate to the policy before checking it. 183 func TestCachingDatalogValidatePeerAttestation(t *testing.T) { 184 network := "tcp" 185 addr := "localhost:0" 186 ttl := int64(1) 187 tmpDir := "/tmp/domain_test" 188 189 // Set up the TaoCA. 190 ch := make(chan bool) 191 cal, err := net.Listen(network, addr) 192 if err != nil { 193 t.Fatal(err) 194 } 195 defer cal.Close() 196 addr = cal.Addr().String() 197 198 // Set up the policy domain and a public, cached version. 199 policy, pub, err := makeTestDomains(tmpDir, network, addr, ttl) 200 if err != nil { 201 t.Fatal(err) 202 } 203 defer os.RemoveAll(tmpDir) 204 defer os.RemoveAll(tmpDir + ".pub") 205 206 // Set up policy. A key being authorized to execute is of course nonsense; 207 // this is only meant to test that ValidatePeerAttestation() properly adds 208 // the endoresement to the policy. 209 rule := "(forall K: TrustedKey(K) implies Authorized(K, \"Execute\"))" 210 if err := policy.Guard.AddRule(rule); err != nil { 211 t.Errorf("could not add rule : %s", err) 212 return 213 } 214 215 // Generate a set of keys for the Tao-delegated server. 216 k, err := NewTemporaryTaoDelegatedKeys(Signing|Crypting|Deriving, nil) 217 if err != nil { 218 t.Error("failed to generate keys:", err) 219 return 220 } 221 k.dir = tmpDir 222 223 // Generate an attesation of the statements: "k.VerifyingKey speaks for 224 // key(K)" and "TrustedKey(key(K))" signed by the policy key and set to 225 // k.Delegation. 226 prin := auth.NewKeyPrin([]byte("This is a terrible key.")) 227 228 pred := auth.Pred{ 229 Name: "TrustedKey", 230 Arg: []auth.Term{prin}, 231 } 232 233 sf := auth.Speaksfor{ 234 Delegate: k.SigningKey.ToPrincipal(), 235 Delegator: prin, 236 } 237 238 stmt := auth.Says{ 239 Speaker: policy.Keys.SigningKey.ToPrincipal(), 240 Time: nil, 241 Expiration: nil, 242 Message: sf, 243 } 244 245 if k.Delegation, err = GenerateAttestation(policy.Keys.SigningKey, nil, stmt); err != nil { 246 t.Error("failed to attest to speaksfor:", err) 247 return 248 } 249 250 e := auth.Says{ 251 Speaker: policy.Keys.SigningKey.ToPrincipal(), 252 Message: pred, 253 } 254 255 ea, err := GenerateAttestation(policy.Keys.SigningKey, nil, e) 256 if err != nil { 257 t.Error("failed to attest to endorsement:", err) 258 return 259 } 260 261 eab, err := proto.Marshal(ea) 262 if err != nil { 263 t.Error("failed to marshal attested endorsement:", err) 264 return 265 } 266 k.Delegation.SerializedEndorsements = [][]byte{eab} 267 268 // Generate an x509 certificate for the Tao-delegated server. 269 signerAlg := SignerTypeFromSuiteName(TaoCryptoSuite) 270 if signerAlg == nil { 271 t.Error("Cant get signer alg from ciphersuite") 272 } 273 pkInt := PublicKeyAlgFromSignerAlg(*signerAlg) 274 skInt := SignatureAlgFromSignerAlg(*signerAlg) 275 if pkInt < 0 || skInt < 0 { 276 t.Error("Cant get x509 signer alg from signer alg") 277 } 278 k.Cert, err = k.SigningKey.CreateSelfSignedX509(pkInt, skInt, 1, 279 &pkix.Name{Organization: []string{"Identity of some Tao service"}}) 280 if err != nil { 281 t.Error("failed to generate x509 certificate:", err) 282 return 283 } 284 285 // Run the TaoCA. This handles one request and then exits. 286 go runTCCA(t, cal, policy.Keys, policy.Guard, ch) 287 288 // Add any verified predicates to the policy. This will cause a 289 // policy query to the TaoCA. 290 if err = AddEndorsements(pub.Guard, k.Delegation, pub.Keys.VerifyingKey); err != nil { 291 t.Error("failed to add endorsements:", err) 292 t.Errorf("pub verifier key is %v\n", pub.Keys.VerifyingKey.ToPrincipal()) 293 t.Errorf("policy ssigning key is %v\n", policy.Keys.SigningKey.ToPrincipal()) 294 t.Errorf("k signing key is %v\n", k.SigningKey.ToPrincipal()) 295 return 296 } 297 298 <-ch 299 300 // Finally, the client verifies the Tao-delegated server is allowed to 301 // execute. 302 if err = ValidatePeerAttestation(k.Delegation, k.Cert, pub.Guard); err != nil { 303 t.Error("failed to verity attestation:", err) 304 } 305 }