// Create creates a service with the given config. func (s *SvcManager) Create(name string, conf common.Conf) error { serviceStartName := "LocalSystem" var passwd string if !series.IsWindowsNano(series.HostSeries()) { password, err := getPassword() if err != nil { return errors.Trace(err) } passwd = password serviceStartName = jujudUser } cfg := mgr.Config{ Dependencies: []string{"Winmgmt"}, ErrorControl: mgr.ErrorSevere, StartType: mgr.StartAutomatic, DisplayName: conf.Desc, ServiceStartName: serviceStartName, Password: passwd, } // mgr.CreateService actually does correct argument escaping itself. There is no // need for quoted strings of any kind passed to this function. It takes in // a binary name, and an array or arguments. service, err := s.mgr.CreateService(name, conf.ServiceBinary, cfg, conf.ServiceArgs...) if err != nil { return errors.Trace(err) } defer service.Close() err = s.ensureRestartOnFailure(name) if err != nil { return errors.Trace(err) } return nil }
func setACLs(path string, permType aclType, ser string) []string { ruleModel := `$rule = New-Object System.Security.AccessControl.%sAccessRule %s` permModel := `%s = "%s", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"` adminPermVar := `$adminPerm` jujudPermVar := `$jujudPerm` rulesToAdd := []string{ // $adminsGroup must be defined before calling setACLs fmt.Sprintf(permModel, adminPermVar, `$adminsGroup`), fmt.Sprintf(ruleModel, permType, adminPermVar), `$acl.AddAccessRule($rule)`, } if !series.IsWindowsNano(ser) { jujudUserACLRules := []string{ fmt.Sprintf(permModel, jujudPermVar, `jujud`), fmt.Sprintf(ruleModel, permType, jujudPermVar), `$acl.AddAccessRule($rule)`, } rulesToAdd = append(rulesToAdd, jujudUserACLRules...) } aclCmds := []string{ fmt.Sprintf(`$acl = Get-Acl -Path '%s'`, path), // Reset the ACL's on it and add administrator access only. `$acl.SetAccessRuleProtection($true, $false)`, fmt.Sprintf(`Set-Acl -Path '%s' -AclObject $acl`, path), } return append(aclCmds[:2], append(rulesToAdd, aclCmds[2:]...)...) }
func (w *windowsConfigure) ConfigureBasic() error { tmpDir, err := paths.TempDir(w.icfg.Series) if err != nil { return err } renderer := w.conf.ShellRenderer() dataDir := renderer.FromSlash(w.icfg.DataDir) baseDir := renderer.FromSlash(filepath.Dir(tmpDir)) binDir := renderer.Join(baseDir, "bin") w.conf.AddScripts(windowsPowershellHelpers) // The jujud user only gets created on non-nano versions for now. if !series.IsWindowsNano(w.icfg.Series) { w.conf.AddScripts(addJujuUser) } w.conf.AddScripts( // Some providers create a baseDir before this step, but we need to // make sure it exists before applying icacls fmt.Sprintf(`mkdir -Force "%s"`, renderer.FromSlash(baseDir)), fmt.Sprintf(`mkdir %s`, renderer.FromSlash(tmpDir)), fmt.Sprintf(`mkdir "%s"`, binDir), fmt.Sprintf(`mkdir "%s\locks"`, renderer.FromSlash(dataDir)), `setx /m PATH "$env:PATH;C:\Juju\bin\"`, // This is necessary for setACLs to work `$adminsGroup = (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544")).Translate([System.Security.Principal.NTAccount])`, fmt.Sprintf(`icacls "%s" /inheritance:r /grant "${adminsGroup}:(OI)(CI)(F)" /t`, renderer.FromSlash(baseDir)), ) // TODO(bogdanteleaga): This, together with the call above, should be using setACLs, once it starts working across all windows versions properly. // Until then, if we change permissions, both this and setACLs should be changed to do the same thing. if !series.IsWindowsNano(w.icfg.Series) { w.conf.AddScripts(fmt.Sprintf(`icacls "%s" /inheritance:r /grant "jujud:(OI)(CI)(F)" /t`, renderer.FromSlash(baseDir))) } noncefile := renderer.Join(dataDir, NonceFile) w.conf.AddScripts( fmt.Sprintf(`Set-Content "%s" "%s"`, noncefile, shquote(w.icfg.MachineNonce)), ) return nil }
func (s *supportedSeriesSuite) TestIsWindowsNano(c *gc.C) { var isWindowsNanoTests = []struct { series string expected bool }{ {"win2016nano", true}, {"win2016", false}, {"win2012r2", false}, {"trusty", false}, } for _, t := range isWindowsNanoTests { c.Assert(series.IsWindowsNano(t.series), gc.Equals, t.expected) } }
func addDownloadToolsCmds(ser string, certificate string, toolsList tools.List) ([]string, error) { var cmds []string var getDownloadFileCmd func(url string) string if series.IsWindowsNano(ser) { parsedCert, err := cert.ParseCert(certificate) if err != nil { return nil, err } caCert := base64.URLEncoding.EncodeToString(parsedCert.Raw) cmds = []string{fmt.Sprintf(`$cacert = "%s"`, caCert), `$cert_bytes = $cacert | %{ ,[System.Text.Encoding]::UTF8.GetBytes($_) }`, `$cert = new-object System.Security.Cryptography.X509Certificates.X509Certificate2(,$cert_bytes)`, `$store = Get-Item Cert:\LocalMachine\AuthRoot`, `$store.Open("ReadWrite")`, `$store.Add($cert)`, } getDownloadFileCmd = func(url string) string { return fmt.Sprintf(`Invoke-FastWebRequest -URI '%s' -OutFile "$binDir\tools.tar.gz"`, url) } } else { cmds = []string{ `$WebClient = New-Object System.Net.WebClient`, `[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}`, `[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12`, } getDownloadFileCmd = func(url string) string { return fmt.Sprintf(`$WebClient.DownloadFile('%s', "$binDir\tools.tar.gz");`, url) } } // Attempt all of the URLs, one after the other, until one succeeds. // If all of the URLs fail, we retry the whole lot. We retry in this // way, rather than retrying individually, to avoid one permanently // bad URL from holding up the download. downloadCmds := make([]string, len(toolsList)) for i, tools := range toolsList { downloadCmds[i] = fmt.Sprintf("{ %s }", getDownloadFileCmd(tools.URL)) } downloadCmd := fmt.Sprintf("ExecRetry { TryExecAll @(%s) }", strings.Join(downloadCmds, ", ")) cmds = append(cmds, downloadCmd) return cmds, nil }