github.com/bshelton229/agent@v3.5.4+incompatible/scripts/vagrant/windows/create-docker-machine.ps1 (about)

     1  param ([String] $machineHome, [String] $machineName, [String] $machineIp)
     2  
     3  if (!(Test-Path $env:USERPROFILE\.docker)) {
     4    mkdir $env:USERPROFILE\.docker
     5  }
     6  
     7  $ipAddresses = ((Get-NetIPAddress -AddressFamily IPv4).IPAddress) -Join ','
     8  
     9  if (!$machineIp) {
    10    $machineIp=(Get-NetIPAddress -AddressFamily IPv4 `
    11      | Where-Object -FilterScript { `
    12        ( ! ($_.InterfaceAlias).StartsWith("vEthernet (") ) `
    13        -And $_.IPAddress -Ne "127.0.0.1" `
    14        -And $_.IPAddress -Ne "10.0.2.15" `
    15      }).IPAddress
    16  }
    17  
    18  $homeDir = $machineHome
    19  if ($machineHome.startsWith('/')) {
    20    $homeDir = "C:$machineHome" # /Users/stefan from Mac -> C:/Users/stefan
    21  }
    22  
    23  function ensureDirs($dirs) {
    24    foreach ($dir in $dirs) {
    25      if (!(Test-Path $dir)) {
    26        mkdir $dir
    27      }
    28    }
    29  }
    30  
    31  # https://docs.docker.com/engine/security/https/
    32  # Thanks to @artisticcheese! https://artisticcheese.wordpress.com/2017/06/10/using-pure-powershell-to-generate-tls-certificates-for-docker-daemon-running-on-windows/
    33  function createCA($serverCertsPath) {
    34    Write-Host "`n=== Generating CA"
    35    $parms = @{
    36      type = "Custom" ;
    37      KeyExportPolicy = "Exportable";
    38      Subject = "CN=Docker TLS Root";
    39      CertStoreLocation = "Cert:\CurrentUser\My";
    40      HashAlgorithm = "sha256";
    41      KeyLength = 4096;
    42      KeyUsage = @("CertSign", "CRLSign");
    43      TextExtension = @("2.5.29.19 ={critical} {text}ca=1")
    44    }
    45    $rootCert = New-SelfSignedCertificate @parms
    46  
    47    Write-Host "`n=== Generating CA public key"
    48    $parms = @{
    49      Path = "$serverCertsPath\ca.pem";
    50      Value = "-----BEGIN CERTIFICATE-----`n" `
    51            + [System.Convert]::ToBase64String($rootCert.RawData, [System.Base64FormattingOptions]::InsertLineBreaks) `
    52            + "`n-----END CERTIFICATE-----";
    53      Encoding = "ASCII";
    54      }
    55    Set-Content @parms
    56    return $rootCert
    57  }
    58  
    59  # https://docs.docker.com/engine/security/https/
    60  function createCerts($rootCert, $serverCertsPath, $serverName, $ipAddresses, $clientCertsPath) {
    61    Write-Host "`n=== Generating Server certificate"
    62    $parms = @{
    63      CertStoreLocation = "Cert:\CurrentUser\My";
    64      Signer = $rootCert;
    65      KeyExportPolicy = "Exportable";
    66      Provider = "Microsoft Enhanced Cryptographic Provider v1.0";
    67      Type = "SSLServerAuthentication";
    68      HashAlgorithm = "sha256";
    69      TextExtension = @("2.5.29.37= {text}1.3.6.1.5.5.7.3.1", "2.5.29.17={text}DNS=$serverName&DNS=localhost&IPAddress=$($ipAddresses.Split(',') -Join '&IPAddress=')");
    70      KeyLength = 4096;
    71    }
    72    $serverCert = New-SelfSignedCertificate @parms
    73  
    74    $parms = @{
    75      Path = "$serverCertsPath\server-cert.pem";
    76      Value = "-----BEGIN CERTIFICATE-----`n" `
    77            + [System.Convert]::ToBase64String($serverCert.RawData, [System.Base64FormattingOptions]::InsertLineBreaks) `
    78            + "`n-----END CERTIFICATE-----";
    79      Encoding = "Ascii"
    80    }
    81    Set-Content @parms
    82  
    83    Write-Host "`n=== Generating Server private key"
    84    $privateKeyFromCert = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($serverCert)
    85    $parms = @{
    86      Path = "$serverCertsPath\server-key.pem";
    87      Value = ("-----BEGIN RSA PRIVATE KEY-----`n" `
    88            + [System.Convert]::ToBase64String($privateKeyFromCert.Key.Export([System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob), [System.Base64FormattingOptions]::InsertLineBreaks) `
    89            + "`n-----END RSA PRIVATE KEY-----");
    90      Encoding = "Ascii";
    91    }
    92    Set-Content @parms
    93  
    94    Write-Host "`n=== Generating Client certificate"
    95    $parms = @{
    96      CertStoreLocation = "Cert:\CurrentUser\My";
    97      Subject = "CN=clientCert";
    98      Signer = $rootCert ;
    99      KeyExportPolicy = "Exportable";
   100      Provider = "Microsoft Enhanced Cryptographic Provider v1.0";
   101      TextExtension = @("2.5.29.37= {text}1.3.6.1.5.5.7.3.2") ;
   102      HashAlgorithm = "sha256";
   103      KeyLength = 4096;
   104    }
   105    $clientCert = New-SelfSignedCertificate  @parms
   106  
   107    $parms = @{
   108      Path = "$clientCertsPath\cert.pem" ;
   109      Value = ("-----BEGIN CERTIFICATE-----`n" + [System.Convert]::ToBase64String($clientCert.RawData, [System.Base64FormattingOptions]::InsertLineBreaks) + "`n-----END CERTIFICATE-----");
   110      Encoding = "Ascii";
   111    }
   112    Set-Content @parms
   113  
   114    Write-Host "`n=== Generating Client key"
   115    $clientprivateKeyFromCert = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($clientCert)
   116    $parms = @{
   117      Path = "$clientCertsPath\key.pem";
   118      Value = ("-----BEGIN RSA PRIVATE KEY-----`n" `
   119            + [System.Convert]::ToBase64String($clientprivateKeyFromCert.Key.Export([System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob), [System.Base64FormattingOptions]::InsertLineBreaks) `
   120            + "`n-----END RSA PRIVATE KEY-----");
   121      Encoding = "Ascii";
   122    }
   123    Set-Content @parms
   124  
   125    copy $serverCertsPath\ca.pem $clientCertsPath\ca.pem
   126  }
   127  
   128  function updateConfig($daemonJson, $serverCertsPath) {
   129    $config = @{}
   130    if (Test-Path $daemonJson) {
   131      $config = (Get-Content $daemonJson) -join "`n" | ConvertFrom-Json
   132    }
   133  
   134    $config = $config | Add-Member(@{ `
   135      hosts = @("tcp://0.0.0.0:2376", "npipe://"); `
   136      tlsverify = $true; `
   137      tlscacert = "$serverCertsPath\ca.pem"; `
   138      tlscert = "$serverCertsPath\server-cert.pem"; `
   139      tlskey = "$serverCertsPath\server-key.pem" `
   140      }) -Force -PassThru
   141  
   142    Write-Host "`n=== Creating / Updating $daemonJson"
   143    $config | ConvertTo-Json | Set-Content $daemonJson -Encoding Ascii
   144  }
   145  
   146  function createMachineConfig ($machineName, $machineHome, $machinePath, $machineIp, $serverCertsPath, $clientCertsPath) {
   147    $machineConfigJson = "$machinePath\config.json"
   148  
   149    $config = @"
   150  {
   151      "ConfigVersion": 3,
   152      "Driver": {
   153          "IPAddress": "$machineIp",
   154          "MachineName": "$machineName",
   155          "SSHUser": "none",
   156          "SSHPort": 3389,
   157          "SSHKeyPath": "",
   158          "StorePath": "$machineHome/.docker/machine",
   159          "SwarmMaster": false,
   160          "SwarmHost": "",
   161          "SwarmDiscovery": "",
   162          "EnginePort": 2376,
   163          "SSHKey": ""
   164      },
   165      "DriverName": "generic",
   166      "HostOptions": {
   167          "Driver": "",
   168          "Memory": 0,
   169          "Disk": 0,
   170          "EngineOptions": {
   171              "ArbitraryFlags": [],
   172              "Dns": null,
   173              "GraphDir": "",
   174              "Env": [],
   175              "Ipv6": false,
   176              "InsecureRegistry": [],
   177              "Labels": [],
   178              "LogLevel": "",
   179              "StorageDriver": "",
   180              "SelinuxEnabled": false,
   181              "TlsVerify": true,
   182              "RegistryMirror": [],
   183              "InstallURL": "https://get.docker.com"
   184          },
   185          "SwarmOptions": {
   186              "IsSwarm": false,
   187              "Address": "",
   188              "Discovery": "",
   189              "Agent": false,
   190              "Master": false,
   191              "Host": "tcp://0.0.0.0:3376",
   192              "Image": "swarm:latest",
   193              "Strategy": "spread",
   194              "Heartbeat": 0,
   195              "Overcommit": 0,
   196              "ArbitraryFlags": [],
   197              "ArbitraryJoinFlags": [],
   198              "Env": null,
   199              "IsExperimental": false
   200          },
   201          "AuthOptions": {
   202              "CertDir": "$machineHome/.docker/machine/machines/$machineName",
   203              "CaCertPath": "$machineHome/.docker/machine/machines/$machineName/ca.pem",
   204              "CaPrivateKeyPath": "$machineHome/.docker/machine/machines/$machineName/ca-key.pem",
   205              "CaCertRemotePath": "",
   206              "ServerCertPath": "$machineHome/.docker/machine/machines/$machineName/server.pem",
   207              "ServerKeyPath": "$machineHome/.docker/machine/machines/$machineName/server-key.pem",
   208              "ClientKeyPath": "$machineHome/.docker/machine/machines/$machineName/key.pem",
   209              "ServerCertRemotePath": "",
   210              "ServerKeyRemotePath": "",
   211              "ClientCertPath": "$machineHome/.docker/machine/machines/$machineName/cert.pem",
   212              "ServerCertSANs": [],
   213              "StorePath": "$machineHome/.docker/machine/machines/$machineName"
   214          }
   215      },
   216      "Name": "$machineName"
   217  }
   218  "@
   219  
   220    Write-Host "`n=== Creating / Updating $machineConfigJson"
   221    $config | Set-Content $machineConfigJson -Encoding Ascii
   222  
   223    Write-Host "`n=== Copying Client certificates to $machinePath"
   224    copy $serverCertsPath\ca.pem $machinePath\ca.pem
   225    copy $clientCertsPath\cert.pem $machinePath\cert.pem
   226    copy $clientCertsPath\key.pem $machinePath\key.pem
   227  }
   228  
   229  $dockerData = "$env:ProgramData\docker"
   230  $userPath = "$env:USERPROFILE\.docker"
   231  
   232  ensureDirs @("$dockerData\certs.d", "$dockerData\config", "$userPath")
   233  
   234  $serverCertsPath = "$dockerData\certs.d"
   235  $clientCertsPath = "$userPath"
   236  $rootCert = createCA "$dockerData\certs.d"
   237  
   238  createCerts $rootCert $serverCertsPath $serverName $ipAddresses $clientCertsPath
   239  updateConfig "$dockerData\config\daemon.json" $serverCertsPath
   240  
   241  if ($machineName) {
   242    $machinePath = "$env:USERPROFILE\.docker\machine\machines\$machineName"
   243    ensureDirs @($machinePath)
   244    createMachineConfig $machineName $machineHome $machinePath $machineIp $serverCertsPath $clientCertsPath
   245  }
   246  
   247  Write-Host "`n=== Copying Docker Machine configuration to $homeDir\.docker\machine\machines\$machineName"
   248  if (Test-Path "$homeDir\.docker\machine\machines\$machineName") {
   249    rm -recurse "$homeDir\.docker\machine\machines\$machineName"
   250  }
   251  Copy-Item -Recurse "$env:USERPROFILE\.docker\machine\machines\$machineName" "$homeDir\.docker\machine\machines\$machineName"
   252  
   253  Write-host Restarting Docker
   254  stop-service docker
   255  dockerd --unregister-service
   256  dockerd --register-service
   257  start-service docker
   258  
   259  Write-Host Opening Docker TLS port
   260  & netsh advfirewall firewall add rule name="Docker TLS" dir=in action=allow protocol=TCP localport=2376