github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/apps/tao_admin/tao_admin.go (about) 1 // Copyright (c) 2014, Kevin Walsh. 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 main 16 17 import ( 18 "crypto/rand" 19 "crypto/rsa" 20 "crypto/sha256" 21 "flag" 22 "fmt" 23 "io" 24 "io/ioutil" 25 "os" 26 "path" 27 "strconv" 28 "strings" 29 "syscall" 30 "text/tabwriter" 31 "time" 32 33 "github.com/golang/protobuf/proto" 34 "github.com/google/go-tpm/tpm" 35 "github.com/jlmucb/cloudproxy/go/tao" 36 "github.com/jlmucb/cloudproxy/go/tao/auth" 37 "github.com/jlmucb/cloudproxy/go/util/options" 38 // "github.com/golang/crypto/ssh/terminal" 39 "golang.org/x/crypto/ssh/terminal" 40 ) 41 42 var opts = []options.Option{ 43 // Flags for all/most commands 44 {"tao_domain", "", "<dir>", "Tao domain configuration directory", "all"}, 45 {"quiet", false, "", "Be more quiet", "all"}, 46 {"pass", "", "<password>", "Password for policy private key (Testing only!)", "all"}, 47 48 // Flags for miscellaneous commands 49 {"config_template", "", "<file>", "Configuration template", "init,newsoft,policy"}, 50 51 // Flags for 'newsoft', used to create soft tao keys. 52 {"soft_pass", "", "<pass>", "A password to encrypt the new soft Tao keys", "newsoft"}, 53 54 // Flags for 'init'. If these flags are specified, a public cached version 55 // of the domain will also be created. 56 {"pub_domain_address", "", "<adddress>", "Address of TaoCA for public cached domain", "init"}, 57 {"pub_domain_network", "tcp", "<network>", "Network of TaoCA for public cached domain", "init"}, 58 {"pub_domain_ttl", 30 * time.Second, "<duration>", "Time-to-live of cached policy", "init"}, 59 60 // Flags for 'policy' command, used to change and query the policy rules 61 // used for principal authorization. The strings passed to these rules 62 // depend on the Guard given in the domain/tao. 63 {"canexecute", "", "<prog>", "Path of a program to be authorized to execute", "policy"}, 64 {"retractcanexecute", "", "<prog>", "Path of a program to retract authorization to execute", "policy"}, 65 {"add", "", "<rule>", "A policy rule to be added", "policy"}, 66 {"retract", "", "<rule>", "A policy rule to be retracted", "policy"}, 67 {"show", false, "", "Print the policy after all other policy commands have executed", "policy"}, 68 {"query", "", "<rule>", "A policy query to be checked", "policy"}, 69 {"clear", false, "", "Clear all policy rules before other changes", "policy"}, 70 {"add_programs", false, "", "Add the program hashes to the policy", "policy"}, 71 {"add_containers", false, "", "Add the container hashes to the policy", "policy"}, 72 {"add_host", false, "", "Add the host to the policy", "policy"}, 73 {"add_vms", false, "", "Add VMs to the policy", "policy"}, 74 {"add_linux_host", false, "", "Add LinuxHost to the policy", "policy"}, 75 {"add_guard", false, "", "Add a trusted guard to the policy", "policy"}, 76 {"add_tpm", false, "", "Add trusted platform module to the policy", "policy"}, 77 {"add_tpm2", false, "", "Add trusted platform module 2.0 to the policy", "policy"}, 78 79 // Flags for 'user' command, used to create new user keys. 80 {"user_key_details", "", "<file>", "File containing an X509Details proto", "user"}, 81 {"user_key_path", "usercreds", "<file>", "Key path", "user"}, 82 {"user_pass", "", "<pass>", "A password for the new user (Testing only!)", "user"}, 83 84 // Flags for the 'principal' option, used to compute principal hashes. 85 {"program", "", "<file>", "Path to a program to be hashed", "principal"}, 86 {"container", "", "<file>", "Path to a container to be hashed", "principal"}, 87 {"tpm", false, "", "Show the TPM principal name", "principal"}, 88 {"soft", "", "<dir>", "Path to a linux host directory with a soft Tao key", "principal"}, 89 } 90 91 func init() { 92 options.Add(opts...) 93 } 94 95 var noise = ioutil.Discard 96 97 func help() { 98 w := new(tabwriter.Writer) 99 w.Init(os.Stderr, 4, 0, 2, ' ', 0) 100 av0 := path.Base(os.Args[0]) 101 102 fmt.Fprintf(w, "Administrative utility for Tao Domain.\n") 103 fmt.Fprintf(w, "Usage:\n") 104 fmt.Fprintf(w, " %s newsoft [options] <dir>\t Create a soft tao key set\n", av0) 105 fmt.Fprintf(w, " %s init [options]\t Initialize a new domain\n", av0) 106 fmt.Fprintf(w, " %s policy [options]\t Manage authorization policies\n", av0) 107 fmt.Fprintf(w, " %s user [options]\t Create user keys\n", av0) 108 fmt.Fprintf(w, " %s principal [options]\t Display principal names/hashes\n", av0) 109 fmt.Fprintf(w, "\n") 110 111 categories := []options.Category{ 112 {"all", "Basic options for most commands"}, 113 {"newsoft", "Options for 'newsoft' command"}, 114 {"init", "Options for 'init' command"}, 115 {"policy", "Options for 'policy' command"}, 116 {"user", "Options for 'user' command"}, 117 {"principal", "Options for 'principal' command"}, 118 {"logging", "Options to control log output"}, 119 } 120 options.ShowRelevant(w, categories...) 121 122 w.Flush() 123 } 124 125 func main() { 126 flag.Usage = help 127 128 // Get options before the command verb 129 flag.Parse() 130 // Get command verb 131 cmd := "help" 132 if flag.NArg() > 0 { 133 cmd = flag.Arg(0) 134 } 135 // Get options after the command verb 136 if flag.NArg() > 1 { 137 flag.CommandLine.Parse(flag.Args()[1:]) 138 } 139 140 if !*options.Bool["quiet"] { 141 noise = os.Stdout 142 } 143 144 switch cmd { 145 case "help": 146 help() 147 case "newsoft": 148 createSoftTaoKeys() 149 case "init": 150 createDomain() 151 case "policy": 152 managePolicy() 153 case "user": 154 createUserKeys() 155 case "principal": 156 outputPrincipal() 157 default: 158 options.Usage("Unrecognized command: %s", cmd) 159 } 160 } 161 162 // Read the tao_admin domain template for default configuration info. 163 var savedTemplate *tao.DomainTemplate 164 165 func template() *tao.DomainTemplate { 166 if savedTemplate == nil { 167 configTemplate := *options.String["config_template"] 168 if configTemplate == "" { 169 options.Usage("Must supply -config_template") 170 } 171 savedTemplate = new(tao.DomainTemplate) 172 pbtext, err := ioutil.ReadFile(configTemplate) 173 options.FailIf(err, "Can't read config template") 174 err = proto.UnmarshalText(string(pbtext), savedTemplate) 175 options.FailIf(err, "Can't parse config template: %s", configTemplate) 176 } 177 return savedTemplate 178 } 179 180 func domainPath() string { 181 if path := *options.String["tao_domain"]; path != "" { 182 return path 183 } 184 if path := os.Getenv("TAO_DOMAIN"); path != "" { 185 return path 186 } 187 options.Usage("Must supply -tao_domain or set $TAO_DOMAIN") 188 return "" 189 } 190 191 func configPath() string { 192 return path.Join(domainPath(), "tao.config") 193 } 194 195 func managePolicy() { 196 197 // Handle queries first 198 if query := *options.String["query"]; query != "" { 199 queryGuard(query) 200 return 201 } 202 203 // Load domain 204 pwd := getKey("domain policy key password", "pass") 205 domain, err := tao.LoadDomain(configPath(), pwd) 206 options.FailIf(err, "Can't load domain") 207 208 // Clear all the policy stored by the Guard. 209 if *options.Bool["clear"] { 210 domain.Guard.Clear() 211 err := domain.Save() 212 options.FailIf(err, "Can't save domain") 213 } 214 215 // Add permissions 216 if canExecute := *options.String["canexecute"]; canExecute != "" { 217 host := template().GetHostName() 218 addExecute(canExecute, host, domain) 219 } 220 if add := *options.String["add"]; add != "" { 221 fmt.Fprintf(noise, "Adding policy rule: %s\n", add) 222 err := domain.Guard.AddRule(add) 223 options.FailIf(err, "Can't add rule to domain") 224 err = domain.Save() 225 options.FailIf(err, "Can't save domain") 226 } 227 if *options.Bool["add_programs"] { 228 host := template().GetHostName() 229 addProgramRules(host, domain) 230 } 231 if *options.Bool["add_containers"] { 232 host := template().GetHostName() 233 addContainerRules(host, domain) 234 } 235 if domain.Config.DomainInfo.GetGuardType() == "Datalog" { 236 if *options.Bool["add_vms"] { 237 addVMRules(domain) 238 } 239 if *options.Bool["add_linux_host"] { 240 addLinuxHostRules(domain) 241 } 242 if *options.Bool["add_host"] { 243 host := template().GetHostName() 244 addHostRules(host, domain) 245 } 246 if *options.Bool["add_guard"] { 247 addGuardRules(domain) 248 } 249 if *options.Bool["add_tpm"] { 250 addTPMRules(domain) 251 } 252 if *options.Bool["add_tpm2"] { 253 addTPM2Rules(domain) 254 } 255 } 256 257 // Retract permissions 258 if retract := *options.String["retract"]; retract != "" { 259 fmt.Fprintf(noise, "Retracting policy rule: %s\n", retract) 260 err := domain.Guard.RetractRule(retract) 261 options.FailIf(err, "Can't retract rule from domain") 262 err = domain.Save() 263 options.FailIf(err, "Can't save domain") 264 } 265 if retractCanExecute := *options.String["retractcanexecute"]; retractCanExecute != "" { 266 host := template().GetHostName() 267 retractExecute(retractCanExecute, host, domain) 268 } 269 270 // Print the policy after all commands are executed. 271 if *options.Bool["show"] { 272 fmt.Print(domain.Guard.String()) 273 } 274 } 275 276 func hash(p string) ([]byte, error) { 277 // If the path is not absolute, then try $GOPATH/bin/path if it exists. 278 realPath := p 279 if !path.IsAbs(p) { 280 // TODO(kwalsh) handle case where GOPATH has multiple paths 281 gopath := os.Getenv("GOPATH") 282 if gopath != "" { 283 realPath = path.Join(path.Join(gopath, "bin"), realPath) 284 } 285 } 286 file, err := os.Open(realPath) 287 if err != nil { 288 return nil, err 289 } 290 hasher := sha256.New() 291 _, err = io.Copy(hasher, file) 292 options.FailIf(err, "Can't hash file") 293 return hasher.Sum(nil), nil 294 } 295 296 func makeHostPrin(host string) auth.Prin { 297 if host == "" { 298 options.Usage("The domain template must contain a Tao host in host_name") 299 } 300 var prin auth.Prin 301 _, err := fmt.Sscanf(host, "%v", &prin) 302 options.FailIf(err, "Can't create host principal") 303 return prin 304 } 305 306 func makeProgramSubPrin(prog string) (auth.SubPrin, error) { 307 // TODO(tmroeder): This assumes no IDs, and it assumes linux hosts. 308 id := uint(0) 309 h, err := hash(prog) 310 if err != nil { 311 return auth.SubPrin{}, err 312 } 313 return tao.FormatProcessSubprin(id, h), nil 314 } 315 316 func makeVMSubPrin(prog string) (auth.SubPrin, error) { 317 // TODO(tmroeder): This assumes no IDs, and it assumes linux hosts. 318 id := uint(0) 319 h, err := hash(prog) 320 if err != nil { 321 return auth.SubPrin{}, err 322 } 323 return tao.FormatCoreOSSubprin(id, h), nil 324 } 325 326 func makeLinuxHostSubPrin(prog string) (auth.SubPrin, error) { 327 // TODO(tmroeder): This assumes no IDs, and it assumes linux hosts. 328 id := uint(0) 329 h, err := hash(prog) 330 if err != nil { 331 return auth.SubPrin{}, err 332 } 333 return tao.FormatLinuxHostSubprin(id, h), nil 334 } 335 336 func makeContainerSubPrin(prog string) (auth.SubPrin, error) { 337 // TODO(tmroeder): This assumes no IDs 338 id := uint(0) 339 h, err := hash(prog) 340 if err != nil { 341 return auth.SubPrin{}, err 342 } 343 return tao.FormatDockerSubprin(id, h), nil 344 } 345 346 // TODO(tmroeder): The keys for the TPM2 have to already be created here so 347 // that we can produce the name of the TPM2 key. For now, this just returns a 348 // dummy key. 349 func makeTPM2Prin(tpmPath string, pcrNums []int) auth.Prin { 350 // TODO(tmroeder): The following key is generated on the spot. This should 351 // instead be the key read from a file. 352 privKey, err := rsa.GenerateKey(rand.Reader, 2048) 353 options.FailIf(err, "Can't generate a temp RSA key") 354 355 // Open a connection to the TPM. 356 tpmFile, err := os.OpenFile(tpmPath, os.O_RDWR, 0) 357 options.FailIf(err, "Can't access TPM") 358 359 pcrVals, err := tao.ReadTPM2PCRs(tpmFile, pcrNums) 360 tpmFile.Close() 361 options.FailIf(err, "Can't get the PCRs from a TPM 2.0") 362 363 prin, err := tao.MakeTPM2Prin(&privKey.PublicKey, pcrNums, pcrVals) 364 options.FailIf(err, "Can't create a TPM2 principal") 365 return prin 366 } 367 368 func makeTPMPrin(tpmPath, aikFile string, pcrNums []int) auth.Prin { 369 // Read AIK blob (TPM's public key). 370 aikblob, err := ioutil.ReadFile(aikFile) 371 options.FailIf(err, "Can't read TPM aik file") 372 373 verifier, err := tpm.UnmarshalRSAPublicKey(aikblob) 374 options.FailIf(err, "Can't parse TPM key") 375 376 // Open a connection to the TPM. 377 tpmFile, err := os.OpenFile(tpmPath, os.O_RDWR, 0) 378 options.FailIf(err, "Can't access TPM") 379 380 // Read registers corresponding to pcrNums. 381 pcrVals, err := tao.ReadPCRs(tpmFile, pcrNums) 382 tpmFile.Close() 383 options.FailIf(err, "Can't read PCRs from TPM") 384 385 // Construct a TPM principal. 386 prin, err := tao.MakeTPMPrin(verifier, pcrNums, pcrVals) 387 options.FailIf(err, "Can't create TPM principal") 388 389 return prin 390 } 391 392 func getKey(prompt, name string) []byte { 393 if input := *options.String[name]; input != "" { 394 fmt.Fprintf(os.Stderr, "Warning: Passwords on the command line are not secure. Use -%s option only for testing.\n", name) 395 return []byte(input) 396 } else { 397 // Get the password from the user. 398 fmt.Print(prompt + ": ") 399 pwd, err := terminal.ReadPassword(syscall.Stdin) 400 options.FailIf(err, "Can't get password") 401 fmt.Println() 402 return pwd 403 } 404 } 405 406 func createSoftTaoKeys() { 407 dt := template() 408 409 args := flag.Args() 410 if len(args) != 1 { 411 options.Usage("Must supply a path for the new key set") 412 } 413 keypath := args[0] 414 415 pwd := getKey("soft tao key password", "soft_pass") 416 417 k, err := tao.NewOnDiskPBEKeys(tao.Signing|tao.Crypting|tao.Deriving, pwd, keypath, tao.NewX509Name(dt.Config.X509Info)) 418 options.FailIf(err, "Can't create keys") 419 420 fmt.Println(k.VerifyingKey.ToPrincipal()) 421 } 422 423 func createDomain() { 424 dt := template() 425 if dt.Config.DomainInfo.GetPolicyKeysPath() == "" { 426 options.Usage("Must supply a policy_keys_path in the domain configuration") 427 } 428 429 pwd := getKey("domain policy key password", "pass") 430 431 domain, err := tao.CreateDomain(*dt.Config, configPath(), pwd) 432 options.FailIf(err, "Can't create domain") 433 434 if domain.Config.DomainInfo.GetGuardType() == "Datalog" { 435 // Add any rules specified in the domain template. 436 for _, rule := range dt.DatalogRules { 437 err := domain.Guard.AddRule(rule) 438 options.FailIf(err, "Can't add rule to domain") 439 } 440 } else if domain.Config.DomainInfo.GetGuardType() == "ACLs" { 441 for _, rule := range dt.AclRules { 442 err := domain.Guard.AddRule(rule) 443 options.FailIf(err, "Can't add rule to domain") 444 } 445 } 446 447 err = domain.Save() 448 options.FailIf(err, "Can't save domain") 449 450 // Optionally, create a public cached domain. 451 if addr := *options.String["pub_domain_address"]; addr != "" { 452 net := *options.String["pub_domain_network"] 453 ttl := *options.Duration["pub_domain_ttl"] 454 _, err = domain.CreatePublicCachedDomain(net, addr, int64(ttl)) 455 options.FailIf(err, "Can't create public cached domain") 456 } 457 } 458 459 func queryGuard(query string) { 460 domain, err := tao.LoadDomain(configPath(), nil) 461 options.FailIf(err, "Can't load domain") 462 463 ok, err := domain.Guard.Query(query) 464 options.FailIf(err, "Can't process query") 465 if ok { 466 fmt.Println("The policy implies the statement.") 467 } else { 468 fmt.Println("The policy does not imply the statement") 469 } 470 } 471 472 func addExecute(path, host string, domain *tao.Domain) { 473 prin := makeHostPrin(host) 474 subprin, err := makeProgramSubPrin(path) 475 if err == nil { 476 prog := prin.MakeSubprincipal(subprin) 477 fmt.Fprintf(noise, "Authorizing program to execute:\n"+ 478 " path: %s\n"+ 479 " host: %s\n"+ 480 " name: %s\n", path, prin, subprin) 481 err := domain.Guard.Authorize(prog, "Execute", nil) 482 options.FailIf(err, "Can't authorize program in domain") 483 err = domain.Save() 484 options.FailIf(err, "Can't save domain") 485 } 486 } 487 488 func retractExecute(path, host string, domain *tao.Domain) { 489 prin := makeHostPrin(host) 490 subprin, err := makeProgramSubPrin(path) 491 if err == nil { 492 prog := prin.MakeSubprincipal(subprin) 493 fmt.Fprintf(noise, "Retracting program authorization to execute:\n"+ 494 " path: %s\n"+ 495 " host: %s\n"+ 496 " name: %s\n", path, prin, subprin) 497 err := domain.Guard.Retract(prog, "Execute", nil) 498 options.FailIf(err, "Can't retract program authorization from domain") 499 } 500 } 501 502 func addACLPrograms(host string, domain *tao.Domain) { 503 if host == "" { 504 return 505 } 506 dt := template() 507 prin := makeHostPrin(host) 508 for _, p := range dt.ProgramPaths { 509 subprin, err := makeProgramSubPrin(p) 510 if err != nil { 511 continue 512 } 513 prog := prin.MakeSubprincipal(subprin) 514 err = domain.Guard.Authorize(prog, "Execute", nil) 515 options.FailIf(err, "Can't authorize program in domain") 516 } 517 for _, vm := range dt.VmPaths { 518 vmPrin, err := makeVMSubPrin(vm) 519 if err != nil { 520 continue 521 } 522 for _, lh := range dt.LinuxHostPaths { 523 lhPrin, err := makeLinuxHostSubPrin(lh) 524 if err != nil { 525 continue 526 } 527 var lsp auth.SubPrin 528 lsp = append(lsp, vmPrin...) 529 lsp = append(lsp, lhPrin...) 530 lprog := prin.MakeSubprincipal(lsp) 531 err = domain.Guard.Authorize(lprog, "Execute", nil) 532 options.FailIf(err, "Can't authorize program in domain") 533 534 for _, p := range dt.ProgramPaths { 535 subprin, err := makeProgramSubPrin(p) 536 if err != nil { 537 continue 538 } 539 var sp auth.SubPrin 540 sp = append(sp, vmPrin...) 541 sp = append(sp, lhPrin...) 542 sp = append(sp, subprin...) 543 prog := prin.MakeSubprincipal(sp) 544 err = domain.Guard.Authorize(prog, "Execute", nil) 545 options.FailIf(err, "Can't authorize program in domain") 546 547 var gsp auth.SubPrin 548 gsp = append(gsp, vmPrin...) 549 gsp = append(gsp, lhPrin...) 550 gsp = append(gsp, domain.Guard.Subprincipal()...) 551 gsp = append(gsp, subprin...) 552 gprog := prin.MakeSubprincipal(gsp) 553 err = domain.Guard.Authorize(gprog, "Execute", nil) 554 options.FailIf(err, "Can't authorize program in domain") 555 } 556 } 557 } 558 } 559 560 func addProgramRules(host string, domain *tao.Domain) { 561 dt := template() 562 if domain.Config.DomainInfo.GetGuardType() == "Datalog" { 563 // Add the hashes of any programs given in the template. 564 for _, p := range dt.ProgramPaths { 565 prin, err := makeProgramSubPrin(p) 566 if err != nil { 567 continue 568 } 569 pt := auth.PrinTail{Ext: prin} 570 pred := auth.MakePredicate(dt.GetProgramPredicateName(), pt) 571 err = domain.Guard.AddRule(fmt.Sprint(pred)) 572 options.FailIf(err, "Can't add rule to domain") 573 } 574 } else if domain.Config.DomainInfo.GetGuardType() == "ACLs" { 575 addACLPrograms(host, domain) 576 } 577 err := domain.Save() 578 options.FailIf(err, "Can't save domain") 579 } 580 581 func addContainerRules(host string, domain *tao.Domain) { 582 dt := template() 583 if domain.Config.DomainInfo.GetGuardType() == "Datalog" { 584 for _, c := range dt.ContainerPaths { 585 prin, err := makeContainerSubPrin(c) 586 if err != nil { 587 continue 588 } 589 pt := auth.PrinTail{Ext: prin} 590 pred := auth.MakePredicate(dt.GetContainerPredicateName(), pt) 591 err = domain.Guard.AddRule(fmt.Sprint(pred)) 592 options.FailIf(err, "Can't add rule to domain") 593 } 594 } else if domain.Config.DomainInfo.GetGuardType() == "ACLs" && host != "" { 595 prin := makeHostPrin(host) 596 for _, p := range dt.ContainerPaths { 597 subprin, err := makeContainerSubPrin(p) 598 if err != nil { 599 continue 600 } 601 prog := prin.MakeSubprincipal(subprin) 602 err = domain.Guard.Authorize(prog, "Execute", nil) 603 options.FailIf(err, "Can't authorize program in domain") 604 } 605 } 606 err := domain.Save() 607 options.FailIf(err, "Can't save domain") 608 } 609 610 func addVMRules(domain *tao.Domain) { 611 dt := template() 612 for _, c := range dt.VmPaths { 613 prin, err := makeVMSubPrin(c) 614 if err != nil { 615 continue 616 } 617 pt := auth.PrinTail{Ext: prin} 618 pred := auth.MakePredicate(dt.GetVmPredicateName(), pt) 619 err = domain.Guard.AddRule(fmt.Sprint(pred)) 620 options.FailIf(err, "Can't add rule to domain") 621 } 622 // The ACLs need the full name, so that only happens for containers and 623 // programs. 624 err := domain.Save() 625 options.FailIf(err, "Can't save domain") 626 } 627 628 func addLinuxHostRules(domain *tao.Domain) { 629 dt := template() 630 for _, c := range dt.LinuxHostPaths { 631 prin, err := makeLinuxHostSubPrin(c) 632 if err != nil { 633 continue 634 } 635 pt := auth.PrinTail{Ext: prin} 636 pred := auth.MakePredicate(dt.GetLinuxHostPredicateName(), pt) 637 err = domain.Guard.AddRule(fmt.Sprint(pred)) 638 options.FailIf(err, "Can't add rule to domain") 639 } 640 // The ACLs need the full name, so that only happens for containers and 641 // programs. 642 err := domain.Save() 643 options.FailIf(err, "Can't save domain") 644 } 645 646 func addHostRules(host string, domain *tao.Domain) { 647 if host == "" { 648 return 649 } 650 dt := template() 651 prin := makeHostPrin(host) 652 pred := auth.MakePredicate(dt.GetHostPredicateName(), prin) 653 err := domain.Guard.AddRule(fmt.Sprint(pred)) 654 options.FailIf(err, "Can't add rule to domain") 655 err = domain.Save() 656 options.FailIf(err, "Can't save domain") 657 } 658 659 func addGuardRules(domain *tao.Domain) { 660 dt := template() 661 subprin := domain.Guard.Subprincipal() 662 pt := auth.PrinTail{Ext: subprin} 663 pred := auth.Pred{ 664 Name: dt.GetGuardPredicateName(), 665 Arg: []auth.Term{pt}, 666 } 667 err := domain.Guard.AddRule(fmt.Sprint(pred)) 668 options.FailIf(err, "Can't add rule to domain") 669 err = domain.Save() 670 options.FailIf(err, "Can't save domain") 671 } 672 673 func addTPMRules(domain *tao.Domain) { 674 dt := template() 675 tpmPath, aikFile, pcrNums := getTPMConfig() 676 prin := makeTPMPrin(tpmPath, aikFile, pcrNums) 677 678 // TrustedOS predicate from PCR principal tail. 679 prinPCRs := auth.PrinTail{Ext: prin.Ext} 680 predTrustedOS := auth.MakePredicate(dt.GetOsPredicateName(), prinPCRs) 681 err := domain.Guard.AddRule(fmt.Sprint(predTrustedOS)) 682 options.FailIf(err, "Can't add rule to domain") 683 684 // TrustedTPM predicate from TPM principal. 685 prin.Ext = nil 686 predTrustedTPM := auth.MakePredicate(dt.GetTpmPredicateName(), prin) 687 err = domain.Guard.AddRule(fmt.Sprint(predTrustedTPM)) 688 options.FailIf(err, "Can't add rule to domain") 689 690 err = domain.Save() 691 options.FailIf(err, "Can't save domain") 692 } 693 694 func addTPM2Rules(domain *tao.Domain) { 695 dt := template() 696 tpmPath, pcrNums := getTPM2Config() 697 prin := makeTPM2Prin(tpmPath, pcrNums) 698 699 // TrustedOS predicate from PCR principal tail. 700 prinPCRs := auth.PrinTail{Ext: prin.Ext} 701 predTrustedOS := auth.MakePredicate(dt.GetOsPredicateName(), prinPCRs) 702 err := domain.Guard.AddRule(fmt.Sprint(predTrustedOS)) 703 options.FailIf(err, "Can't add rule to domain") 704 705 // TrustedTPM predicate from TPM principal. 706 prin.Ext = nil 707 predTrustedTPM2 := auth.MakePredicate(dt.GetTpm2PredicateName(), prin) 708 err = domain.Guard.AddRule(fmt.Sprint(predTrustedTPM2)) 709 options.FailIf(err, "Can't add rule to domain") 710 711 err = domain.Save() 712 options.FailIf(err, "Can't save domain") 713 } 714 715 func createUserKeys() { 716 // Read the X509Details for this user from a text protobuf file. 717 userKeyDetails := *options.String["user_key_details"] 718 xdb, err := ioutil.ReadFile(userKeyDetails) 719 options.FailIf(err, "Can't read user details") 720 var xd tao.X509Details 721 err = proto.UnmarshalText(string(xdb), &xd) 722 options.FailIf(err, "Can't parse user details: %s", userKeyDetails) 723 724 upwd := getKey("user password", "user_pass") 725 pwd := getKey("domain policy key password", "pass") 726 727 domain, err := tao.LoadDomain(configPath(), pwd) 728 options.FailIf(err, "Can't load domain") 729 policyKey := domain.Keys 730 731 subjectName := tao.NewX509Name(&xd) 732 userKeyPath := *options.String["user_key_path"] 733 _, err = tao.NewSignedOnDiskPBEKeys(tao.Signing, upwd, userKeyPath, subjectName, int(xd.GetSerialNumber()), policyKey) 734 options.FailIf(err, "Can't create user signing key") 735 } 736 737 func getTPMConfig() (string, string, []int) { 738 domain, err := tao.LoadDomain(configPath(), nil) 739 options.FailIf(err, "Can't load domain") 740 tpmPath := domain.Config.GetTpmInfo().GetTpmPath() 741 aikFile := domain.Config.GetTpmInfo().GetAikPath() 742 pcrVals := domain.Config.GetTpmInfo().GetPcrs() 743 var pcrNums []int 744 for _, s := range strings.Split(pcrVals, ",") { 745 v, err := strconv.ParseInt(s, 10, 32) 746 options.FailIf(err, "Can't parse TPM PCR spec") 747 748 pcrNums = append(pcrNums, int(v)) 749 } 750 751 return tpmPath, aikFile, pcrNums 752 } 753 754 func getTPM2Config() (string, []int) { 755 domain, err := tao.LoadDomain(configPath(), nil) 756 options.FailIf(err, "Can't load domain") 757 // TODO(tmroeder): This ignores the info path, since it ignores the cert 758 // files. 759 tpmPath := domain.Config.GetTpm2Info().GetTpm2Device() 760 pcrVals := domain.Config.GetTpm2Info().GetTpm2Pcrs() 761 // TODO(tmroeder): This currently ignores the paths to the ek_cert and 762 // quote_cert, since it creates its own keys. 763 var pcrNums []int 764 for _, s := range strings.Split(pcrVals, ",") { 765 v, err := strconv.ParseInt(s, 10, 32) 766 options.FailIf(err, "Can't parse TPM PCR spec") 767 768 pcrNums = append(pcrNums, int(v)) 769 } 770 771 return tpmPath, pcrNums 772 } 773 774 func outputPrincipal() { 775 if path := *options.String["program"]; path != "" { 776 subprin, err := makeProgramSubPrin(path) 777 options.FailIf(err, "Can't create program principal") 778 pt := auth.PrinTail{Ext: subprin} 779 fmt.Println(pt) 780 } 781 if path := *options.String["container"]; path != "" { 782 subprin, err := makeContainerSubPrin(path) 783 options.FailIf(err, "Can't create container principal") 784 pt := auth.PrinTail{Ext: subprin} 785 fmt.Println(pt) 786 } 787 if *options.Bool["tpm"] { 788 tpmPath, aikFile, pcrVals := getTPMConfig() 789 prin := makeTPMPrin(tpmPath, aikFile, pcrVals) 790 // In the domain template the host name is in quotes. We need to escape 791 // quote strings in the Principal string so that domain_template.pb gets 792 // parsed correctly. 793 name := strings.Replace(prin.String(), "\"", "\\\"", -1) 794 fmt.Println(name) 795 } 796 if *options.Bool["tpm2"] { 797 tpmPath, pcrVals := getTPM2Config() 798 prin := makeTPM2Prin(tpmPath, pcrVals) 799 // In the domain template the host name is in quotes. We need to escape 800 // quote strings in the Principal string so that domain_template.pb gets 801 // parsed correctly. 802 name := strings.Replace(prin.String(), "\"", "\\\"", -1) 803 fmt.Println(name) 804 } 805 if lhpath := *options.String["soft"]; lhpath != "" { 806 if !path.IsAbs(lhpath) { 807 lhpath = path.Join(domainPath(), lhpath) 808 } 809 k, err := tao.NewOnDiskPBEKeys(tao.Signing, nil, lhpath, nil) 810 options.FailIf(err, "Can't create soft tao keys") 811 fmt.Println(k.VerifyingKey.ToPrincipal()) 812 } 813 }