github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/cloudconfig/userdatacfg_win.go (about)

     1  // Copyright 2012, 2013, 2014, 2015 Canonical Ltd.
     2  // Copyright 2014, 2015 Cloudbase Solutions SRL
     3  // Licensed under the AGPLv3, see LICENCE file for details.
     4  
     5  package cloudconfig
     6  
     7  import (
     8  	"encoding/json"
     9  	"fmt"
    10  	"path/filepath"
    11  
    12  	"github.com/juju/errors"
    13  	"github.com/juju/names"
    14  	"github.com/juju/utils/featureflag"
    15  
    16  	"github.com/juju/juju/juju/osenv"
    17  	"github.com/juju/juju/juju/paths"
    18  )
    19  
    20  type windowsConfigure struct {
    21  	baseConfigure
    22  }
    23  
    24  // Configure updates the provided cloudinit.Config with
    25  // configuration to initialize a Juju machine agent.
    26  func (w *windowsConfigure) Configure() error {
    27  	if err := w.ConfigureBasic(); err != nil {
    28  		return err
    29  	}
    30  	return w.ConfigureJuju()
    31  }
    32  
    33  func (w *windowsConfigure) ConfigureBasic() error {
    34  
    35  	series := w.icfg.Series
    36  	tmpDir, err := paths.TempDir(series)
    37  	if err != nil {
    38  		return err
    39  	}
    40  	renderer := w.conf.ShellRenderer()
    41  	dataDir := renderer.FromSlash(w.icfg.DataDir)
    42  	baseDir := renderer.FromSlash(filepath.Dir(tmpDir))
    43  	binDir := renderer.Join(baseDir, "bin")
    44  
    45  	w.conf.AddScripts(
    46  		fmt.Sprintf(`%s`, winPowershellHelperFunctions),
    47  		fmt.Sprintf(`icacls "%s" /grant "jujud:(OI)(CI)(F)" /T`, renderer.FromSlash(baseDir)),
    48  		fmt.Sprintf(`mkdir %s`, renderer.FromSlash(tmpDir)),
    49  		fmt.Sprintf(`mkdir "%s"`, binDir),
    50  		fmt.Sprintf(`mkdir "%s\locks"`, renderer.FromSlash(dataDir)),
    51  		fmt.Sprintf(`Start-ProcessAsUser -Command $cmdExe -Arguments '/C setx PATH "%%PATH%%;C:\Juju\bin"' -Credential $jujuCreds`),
    52  	)
    53  	noncefile := renderer.Join(dataDir, NonceFile)
    54  	w.conf.AddScripts(
    55  		fmt.Sprintf(`Set-Content "%s" "%s"`, noncefile, shquote(w.icfg.MachineNonce)),
    56  	)
    57  	return nil
    58  }
    59  
    60  func (w *windowsConfigure) ConfigureJuju() error {
    61  	if err := w.icfg.VerifyConfig(); err != nil {
    62  		return errors.Trace(err)
    63  	}
    64  	if w.icfg.Bootstrap == true {
    65  		// Bootstrap machine not supported on windows
    66  		return errors.Errorf("bootstrapping is not supported on windows")
    67  	}
    68  
    69  	toolsJson, err := json.Marshal(w.icfg.Tools)
    70  	if err != nil {
    71  		return errors.Annotate(err, "while serializing the tools")
    72  	}
    73  	const python = `${env:ProgramFiles(x86)}\Cloudbase Solutions\Cloudbase-Init\Python27\python.exe`
    74  	renderer := w.conf.ShellRenderer()
    75  	w.conf.AddScripts(
    76  		fmt.Sprintf(`$binDir="%s"`, renderer.FromSlash(w.icfg.JujuTools())),
    77  		`$tmpBinDir=$binDir.Replace('\', '\\')`,
    78  		fmt.Sprintf(`mkdir '%s'`, renderer.FromSlash(w.icfg.LogDir)),
    79  		`mkdir $binDir`,
    80  		`$WebClient = New-Object System.Net.WebClient`,
    81  		`[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}`,
    82  		fmt.Sprintf(`ExecRetry { $WebClient.DownloadFile('%s', "$binDir\tools.tar.gz") }`, w.icfg.Tools.URL),
    83  		`$dToolsHash = (Get-FileHash -Algorithm SHA256 "$binDir\tools.tar.gz").hash`,
    84  		fmt.Sprintf(`$dToolsHash > "$binDir\juju%s.sha256"`,
    85  			w.icfg.Tools.Version),
    86  		fmt.Sprintf(`if ($dToolsHash.ToLower() -ne "%s"){ Throw "Tools checksum mismatch"}`,
    87  			w.icfg.Tools.SHA256),
    88  		fmt.Sprintf(`& "%s" -c "import tarfile;archive = tarfile.open('$tmpBinDir\\tools.tar.gz');archive.extractall(path='$tmpBinDir')"`, python),
    89  		`rm "$binDir\tools.tar*"`,
    90  		fmt.Sprintf(`Set-Content $binDir\downloaded-tools.txt '%s'`, string(toolsJson)),
    91  	)
    92  
    93  	for _, cmd := range CreateJujuRegistryKeyCmds() {
    94  		w.conf.AddRunCmd(cmd)
    95  	}
    96  
    97  	machineTag := names.NewMachineTag(w.icfg.MachineId)
    98  	_, err = w.addAgentInfo(machineTag)
    99  	if err != nil {
   100  		return errors.Trace(err)
   101  	}
   102  	return w.addMachineAgentToBoot()
   103  }
   104  
   105  // CreateJujuRegistryKey is going to create a juju registry key and set
   106  // permissions on it such that it's only accessible to administrators
   107  // It is exported because it is used in an upgrade step
   108  func CreateJujuRegistryKeyCmds() []string {
   109  	return []string{
   110  		// Create a registry key for storing juju related information
   111  		fmt.Sprintf(`New-Item -Path '%s'`, osenv.JujuRegistryKey),
   112  		fmt.Sprintf(`$acl = Get-Acl -Path '%s'`, osenv.JujuRegistryKey),
   113  
   114  		// Reset the ACL's on it and add administrator access only.
   115  		`$acl.SetAccessRuleProtection($true, $false)`,
   116  		`$perm = "BUILTIN\Administrators", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"`,
   117  		`$rule = New-Object System.Security.AccessControl.RegistryAccessRule $perm`,
   118  		`$acl.SetAccessRule($rule)`,
   119  		fmt.Sprintf(`Set-Acl -Path '%s' -AclObject $acl`, osenv.JujuRegistryKey),
   120  		// Create a JUJU_DEV_FEATURE_FLAGS entry which may or may not be empty.
   121  		fmt.Sprintf(`New-ItemProperty -Path '%s' -Name '%s'`,
   122  			osenv.JujuRegistryKey,
   123  			osenv.JujuFeatureFlagEnvKey),
   124  		fmt.Sprintf(`Set-ItemProperty -Path '%s' -Name '%s' -Value '%s'`,
   125  			osenv.JujuRegistryKey,
   126  			osenv.JujuFeatureFlagEnvKey,
   127  			featureflag.AsEnvironmentValue()),
   128  	}
   129  }