func addContainerRules(host string, domain *tao.Domain) { dt := template() if domain.Config.DomainInfo.GetGuardType() == "Datalog" { for _, c := range dt.ContainerPaths { prin, err := makeContainerSubPrin(c) if err != nil { continue } pt := auth.PrinTail{Ext: prin} pred := auth.MakePredicate(dt.GetContainerPredicateName(), pt) err = domain.Guard.AddRule(fmt.Sprint(pred)) options.FailIf(err, "Can't add rule to domain") } } else if domain.Config.DomainInfo.GetGuardType() == "ACLs" && host != "" { prin := makeHostPrin(host) for _, p := range dt.ContainerPaths { subprin, err := makeContainerSubPrin(p) if err != nil { continue } prog := prin.MakeSubprincipal(subprin) err = domain.Guard.Authorize(prog, "Execute", nil) options.FailIf(err, "Can't authorize program in domain") } } err := domain.Save() options.FailIf(err, "Can't save domain") }
func generateDomain(t *testing.T) *tao.Domain { domain := tao.Domain{} domain.Keys, domain.Keys.Cert = generatePolicyKey(t) domain.Guard = *generateGuard(t) domain.Config = tao.DomainConfig{X509Info: x509Info} return &domain }
// This function reads in trusted entities from a file at trustedEntitiesPath. In particular, // this file contains the text representation of a trusted_entities proto message, which contains // the Tao names of trusted programs and hosts, information about trusted machines and trusted // machine certificates. // For each such trusted entity, this function adds ACL rules to the domain guard, and saves // the changes before returning. func InitAcls(domain *tao.Domain, trustedEntitiesPath string) error { text, err := ioutil.ReadFile(trustedEntitiesPath) if err != nil { log.Printf("Can't open trusted entities file: %s", trustedEntitiesPath) return err } trustedEntities := TrustedEntities{} err = proto.UnmarshalText(string(text), &trustedEntities) if err != nil { log.Printf("Can't parse trusted entities file: %s", trustedEntitiesPath) return err } for _, programTaoName := range trustedEntities.GetTrustedProgramTaoNames() { var programPrin auth.Prin _, err := fmt.Sscanf(programTaoName, "%v", &programPrin) if err != nil { log.Printf("Can't create program principal from: %s\nError: %s", programTaoName, err) return err } err = domain.Guard.Authorize(programPrin, "Execute", []string{}) if err != nil { log.Printf("Can't authorize principal: %s\nError: %s", programPrin, err) return err } } for _, hostTaoName := range trustedEntities.GetTrustedHostTaoNames() { var hostPrin auth.Prin _, err := fmt.Sscanf(hostTaoName, "%v", &hostPrin) if err != nil { log.Printf("Can't create host principal from: %s\nError: %s", hostTaoName, err) return err } err = domain.Guard.Authorize(hostPrin, "Host", []string{}) if err != nil { log.Printf("Can't authorize principal: %s\nError: %s", hostPrin, err) return err } } for _, machineInfo := range trustedEntities.GetTrustedMachineInfos() { machinePrin := auth.Prin{ Type: "MachineInfo", KeyHash: auth.Str(machineInfo), } err = domain.Guard.Authorize(machinePrin, "Root", []string{}) if err != nil { log.Printf("Can't authorize principal: %s\nError: %s", machinePrin, err) return err } } err = domain.Save() if err != nil { log.Println("Can't save domain.", err) } return err }
func addHostRules(host string, domain *tao.Domain) { if host == "" { return } dt := template() prin := makeHostPrin(host) pred := auth.MakePredicate(dt.GetHostPredicateName(), prin) err := domain.Guard.AddRule(fmt.Sprint(pred)) options.FailIf(err, "Can't add rule to domain") err = domain.Save() options.FailIf(err, "Can't save domain") }
func addGuardRules(domain *tao.Domain) { dt := template() subprin := domain.Guard.Subprincipal() pt := auth.PrinTail{Ext: subprin} pred := auth.Pred{ Name: dt.GetGuardPredicateName(), Arg: []auth.Term{pt}, } err := domain.Guard.AddRule(fmt.Sprint(pred)) options.FailIf(err, "Can't add rule to domain") err = domain.Save() options.FailIf(err, "Can't save domain") }
func addExecute(path, host string, domain *tao.Domain) { prin := makeHostPrin(host) subprin, err := makeProgramSubPrin(path) if err == nil { prog := prin.MakeSubprincipal(subprin) fmt.Fprintf(noise, "Authorizing program to execute:\n"+ " path: %s\n"+ " host: %s\n"+ " name: %s\n", path, prin, subprin) err := domain.Guard.Authorize(prog, "Execute", nil) options.FailIf(err, "Can't authorize program in domain") err = domain.Save() options.FailIf(err, "Can't save domain") } }
func addLinuxHostRules(domain *tao.Domain) { dt := template() for _, c := range dt.LinuxHostPaths { prin, err := makeLinuxHostSubPrin(c) if err != nil { continue } pt := auth.PrinTail{Ext: prin} pred := auth.MakePredicate(dt.GetLinuxHostPredicateName(), pt) err = domain.Guard.AddRule(fmt.Sprint(pred)) options.FailIf(err, "Can't add rule to domain") } // The ACLs need the full name, so that only happens for containers and // programs. err := domain.Save() options.FailIf(err, "Can't save domain") }
func addTPM2Rules(domain *tao.Domain) { dt := template() tpmPath, pcrNums := getTPM2Config() prin := makeTPM2Prin(tpmPath, pcrNums) // TrustedOS predicate from PCR principal tail. prinPCRs := auth.PrinTail{Ext: prin.Ext} predTrustedOS := auth.MakePredicate(dt.GetOsPredicateName(), prinPCRs) err := domain.Guard.AddRule(fmt.Sprint(predTrustedOS)) options.FailIf(err, "Can't add rule to domain") // TrustedTPM predicate from TPM principal. prin.Ext = nil predTrustedTPM2 := auth.MakePredicate(dt.GetTpm2PredicateName(), prin) err = domain.Guard.AddRule(fmt.Sprint(predTrustedTPM2)) options.FailIf(err, "Can't add rule to domain") err = domain.Save() options.FailIf(err, "Can't save domain") }
func addProgramRules(host string, domain *tao.Domain) { dt := template() if domain.Config.DomainInfo.GetGuardType() == "Datalog" { // Add the hashes of any programs given in the template. for _, p := range dt.ProgramPaths { prin, err := makeProgramSubPrin(p) if err != nil { continue } pt := auth.PrinTail{Ext: prin} pred := auth.MakePredicate(dt.GetProgramPredicateName(), pt) err = domain.Guard.AddRule(fmt.Sprint(pred)) options.FailIf(err, "Can't add rule to domain") } } else if domain.Config.DomainInfo.GetGuardType() == "ACLs" { addACLPrograms(host, domain) } err := domain.Save() options.FailIf(err, "Can't save domain") }
func loadHost(domain *tao.Domain, cfg *tao.LinuxHostConfig) (*tao.LinuxHost, error) { var tc tao.Config // Sanity check host type var stacked bool switch cfg.GetType() { case "root": stacked = false case "stacked": stacked = true case "": options.Usage("Must supply -root or -stacked flag") default: options.Usage("Invalid host type: %s", cfg.GetType()) } // Sanity check hosting type hosting := make(map[string]bool) for _, h := range cfg.GetHosting() { switch h { case "process", "docker", "kvm_coreos", "kvm_coreos_linuxhost": hosting[h] = true default: options.Usage("Invalid hosting type: %s", cfg.GetHosting()) } } if len(hosting) == 0 { options.Usage("Must supply -hosting flag") } // For stacked hosts, figure out the channel type: TPM, pipe, file, or unix if stacked { switch cfg.GetParentType() { case "TPM": tc.HostChannelType = "tpm" case "pipe": tc.HostChannelType = "pipe" case "file": tc.HostChannelType = "file" case "unix": tc.HostChannelType = "unix" case "": // leave channel type blank, tao may find it in env vars tc.HostChannelType = "" default: options.Usage("Invalid parent type: %s", cfg.GetParentType()) } // For stacked hosts, we may also have a parent spec from command line tc.HostSpec = cfg.GetParentSpec() // For stacked hosts on a TPM, we may also have tpm info from domain config if domain.Config.TpmInfo != nil { tc.TPMAIKPath = path.Join(apps.TaoDomainPath(), domain.Config.TpmInfo.GetAikPath()) tc.TPMPCRs = domain.Config.TpmInfo.GetPcrs() tc.TPMDevice = domain.Config.TpmInfo.GetTpmPath() } } rulesPath := "" if p := domain.RulesPath(); p != "" { rulesPath = path.Join(apps.TaoDomainPath(), p) } // Create the hosted program factory socketPath := hostPath() if subPath := cfg.GetSocketDir(); subPath != "" { if path.IsAbs(subPath) { socketPath = subPath } else { socketPath = path.Join(socketPath, subPath) } } // TODO(cjpatton) How do the NewLinuxDockerContainterFactory and the // NewLinuxKVMCoreOSHostFactory need to be modified to support the new // CachedGuard? They probably don't. childFactory := make(map[string]tao.HostedProgramFactory) if hosting["process"] { childFactory["process"] = tao.NewLinuxProcessFactory("pipe", socketPath) } if hosting["docker"] { childFactory["docker"] = tao.NewLinuxDockerContainerFactory(socketPath, rulesPath) } if hosting["kvm_coreos"] { // TODO(kwalsh) re-enable this code path in new kvm factory // sshFile := cfg.GetKvmCoreosSshAuthKeys() // if sshFile != "" { // if !path.IsAbs(sshFile) { // sshFile = path.Join(apps.TaoDomainPath(), sshFile) // } // sshKeysCfg, err := io.ReadFile(sshFile) // options.FailIf(err, "Can't read ssh authorized keys") coreOSImage := cfg.GetKvmCoreosImg() if coreOSImage == "" { options.Usage("Must specify -kvm_coreos_image for hosting QEMU/KVM CoreOS") } if !path.IsAbs(coreOSImage) { coreOSImage = path.Join(apps.TaoDomainPath(), coreOSImage) } // TODO(kwalsh) re-enable this code path in new kvm factory // vmMemory := cfg.GetKvmCoreosVmMemory() // if vmMemory == 0 { // vmMemory = 1024 // } var err error childFactory["kvm_coreos"], err = tao.NewKVMCoreOSFactory(coreOSImage, false) options.FailIf(err, "Can't create KVM CoreOS factory") } if hosting["kvm_coreos_linuxhost"] { sshFile := cfg.GetKvmCoreosSshAuthKeys() if sshFile == "" { options.Usage("Must specify -kvm_coreos_ssh_auth_keys for hosting QEMU/KVM CoreOS") } if !path.IsAbs(sshFile) { sshFile = path.Join(apps.TaoDomainPath(), sshFile) } sshKeysCfg, err := tao.CloudConfigFromSSHKeys(sshFile) options.FailIf(err, "Can't read ssh keys") coreOSImage := cfg.GetKvmCoreosImg() if coreOSImage == "" { options.Usage("Must specify -kvm_coreos_image for hosting QEMU/KVM CoreOS") } if !path.IsAbs(coreOSImage) { coreOSImage = path.Join(apps.TaoDomainPath(), coreOSImage) } vmMemory := cfg.GetKvmCoreosVmMemory() if vmMemory == 0 { vmMemory = 1024 } cfg := &tao.CoreOSLinuxhostConfig{ ImageFile: coreOSImage, Memory: int(vmMemory), RulesPath: rulesPath, SSHKeysCfg: sshKeysCfg, } childFactory["kvm_coreos_linuxhost"], err = tao.NewLinuxKVMCoreOSHostFactory(socketPath, cfg) options.FailIf(err, "Can't create KVM CoreOS LinuxHost factory") } if !stacked { pwd := options.Password("root host key password", "pass") return tao.NewRootLinuxHost(hostPath(), domain.Guard, pwd, childFactory) } else { parent := tao.ParentFromConfig(tc) if parent == nil { options.Usage("No host tao available, verify -parent_type (or $%s) and associated variables\n", tao.HostChannelTypeEnvVar) } return tao.NewStackedLinuxHost(hostPath(), domain.Guard, parent, childFactory) } }
func loadHost(domain *tao.Domain, cfg *tao.LinuxHostConfig) (*tao.LinuxHost, error) { var tc tao.Config // Decide host type switch cfg.GetType() { case "root": tc.HostType = tao.Root case "stacked": tc.HostType = tao.Stacked case "": options.Usage("Must supply -hosting flag") default: options.Usage("Invalid host type: %s", cfg.GetType()) } // Decide hosting type switch cfg.GetHosting() { case "process": tc.HostedType = tao.ProcessPipe case "docker": tc.HostedType = tao.DockerUnix case "kvm_coreos": tc.HostedType = tao.KVMCoreOSFile case "": options.Usage("Must supply -hosting flag") default: options.Usage("Invalid hosting type: %s", cfg.GetHosting()) } // For stacked hosts, figure out the channel type: TPM, pipe, file, or unix if tc.HostType == tao.Stacked { switch cfg.GetParentType() { case "TPM": tc.HostChannelType = "tpm" case "pipe": tc.HostChannelType = "pipe" case "file": tc.HostChannelType = "file" case "unix": tc.HostChannelType = "unix" case "": options.Usage("Must supply -parent_type for stacked hosts") default: options.Usage("Invalid parent type: %s", cfg.GetParentType()) } // For stacked hosts on anything but a TPM, we also need parent spec if tc.HostChannelType != "tpm" { tc.HostSpec = cfg.GetParentSpec() if tc.HostSpec == "" { options.Usage("Must supply -parent_spec for non-TPM stacked hosts") } } else { // For stacked hosts on a TPM, we also need info from domain config if domain.Config.TpmInfo == nil { options.Usage("Must provide TPM configuration in the domain to use a TPM") } tc.TPMAIKPath = path.Join(domainPath(), domain.Config.TpmInfo.GetAikPath()) tc.TPMPCRs = domain.Config.TpmInfo.GetPcrs() tc.TPMDevice = domain.Config.TpmInfo.GetTpmPath() } } rulesPath := "" if p := domain.RulesPath(); p != "" { rulesPath = path.Join(domainPath(), p) } // Create the hosted program factory socketPath := hostPath() if subPath := cfg.GetSocketDir(); subPath != "" { if path.IsAbs(subPath) { socketPath = subPath } else { socketPath = path.Join(socketPath, subPath) } } // TODO(cjpatton) How do the NewLinuxDockerContainterFactory and the // NewLinuxKVMCoreOSFactory need to be modified to support the new // CachedGuard? They probably don't. var childFactory tao.HostedProgramFactory switch tc.HostedType { case tao.ProcessPipe: childFactory = tao.NewLinuxProcessFactory("pipe", socketPath) case tao.DockerUnix: childFactory = tao.NewLinuxDockerContainerFactory(socketPath, rulesPath) case tao.KVMCoreOSFile: sshFile := cfg.GetKvmCoreosSshAuthKeys() if sshFile == "" { options.Usage("Must specify -kvm_coreos_ssh_auth_keys for hosting QEMU/KVM CoreOS") } if !path.IsAbs(sshFile) { sshFile = path.Join(domainPath(), sshFile) } sshKeysCfg, err := tao.CloudConfigFromSSHKeys(sshFile) options.FailIf(err, "Can't read ssh keys") coreOSImage := cfg.GetKvmCoreosImg() if coreOSImage == "" { options.Usage("Must specify -kvm_coreos_image for hosting QEMU/KVM CoreOS") } if !path.IsAbs(coreOSImage) { coreOSImage = path.Join(domainPath(), coreOSImage) } vmMemory := cfg.GetKvmCoreosVmMemory() if vmMemory == 0 { vmMemory = 1024 } cfg := &tao.CoreOSConfig{ ImageFile: coreOSImage, Memory: int(vmMemory), RulesPath: rulesPath, SSHKeysCfg: sshKeysCfg, } childFactory, err = tao.NewLinuxKVMCoreOSFactory(socketPath, cfg) options.FailIf(err, "Can't create KVM CoreOS factory") } if tc.HostType == tao.Root { pwd := getKey("root host key password", "pass") return tao.NewRootLinuxHost(hostPath(), domain.Guard, pwd, childFactory) } else { parent := tao.ParentFromConfig(tc) if parent == nil { options.Usage("No host tao available, verify -parent_type or $%s\n", tao.HostChannelTypeEnvVar) } return tao.NewStackedLinuxHost(hostPath(), domain.Guard, tao.ParentFromConfig(tc), childFactory) } }