Skip to content

Conversation

@jstange
Copy link

@jstange jstange commented Oct 10, 2017

The WinRM gem supports certificate authentication. Added some glue to take advantage of it.

My use case invokes bootstraps from Ruby by calling into the library (yeah, I know), so I'm more sure of that than of the actual command-line functionality. I've given the latter little more than a cursory smoke test. It should go something like this:

knife bootstrap windows winrm -t ssl web1.cloudapp.net --winrm-authentication-protocol cert --winrm-client-cert ~/myclient.crt --winrm-client-key ~/myclient.key -f ~/mycert.crt

If it's of use in documentation, below I've pasted an approximation of Powershell we use to get our servers to honor WinRM certificate auth. We don't actually use Administrator internally, but that's probably what most people want, so I've elided that and a few other things.

Set-Item -Path WSMan:\localhost\Service\Auth\Certificate -Value $true

$cacert = Import-Certificate -FilePath $tmp/my-ca-cert.pem -CertStoreLocation Cert:\LocalMachine\Root
$clientcert = Import-Certificate -FilePath $tmp/Administrator-client-cert.pem -CertStoreLocation Cert:\LocalMachine\TrustedPeople

$creds = New-Object System.Management.Automation.PSCredential("Administrator", (ConvertTo-SecureString "mypassword" -AsPlainText -Force))

New-Item -Path WSMan:\localhost\ClientCertificate -Subject 'Administrator@localhost' -URI * -Issuer $cacert.Thumbprint -Force -Credential $creds

Heck, while I'm at it, here's a simplified version of Ruby+OpenSSL that generates our client certificates. The CSR bit:

        key = OpenSSL::PKey::RSA.new 4096
        open("Administrator-client-cert.key", 'w', 0600) { |io|
          io.write key.to_pem
        }
        csr = OpenSSL::X509::Request.new
        csr.version = 3
        csr.subject = OpenSSL::X509::Name.parse "CN=Administrator/O=MyOrgOrWhatever/C=US"
        csr.public_key = key.public_key
        open("Administrator-client-cert.csr", 'w', 0600) { |io|
          io.write csr.to_pem
        }

And the signing by our internal CA:

#  cacert, cakey, and cur_serial loaded in the usual fashion
      csr = OpenSSL::X509::Request.new File.read "Administrator-client-cert.csr"
      key = OpenSSL::PKey::RSA.new File.read "Administrator-client-cert.key"
      sans = ["otherName:1.3.6.1.4.1.311.20.2.3;UTF8:Administrator@localhost"]
      cert = OpenSSL::X509::Certificate.new
      cert.serial = cur_serial
      cert.version = 3
      cert.not_before = Time.now
      cert.not_after = Time.now + 180000000
      cert.subject = csr.subject
      cert.public_key = csr.public_key
      cert.issuer = cacert.subject
      ef = OpenSSL::X509::ExtensionFactory.new
      ef.issuer_certificate = cacert
      ef.subject_certificate = cert
      ef.subject_request = csr
      cert.add_extension(ef.create_extension("keyUsage","nonRepudiation,digitalSignature,keyEncipherment", false))
      cert.add_extension(ef.create_extension("subjectAltName",sans.join(","),false))
      cert.add_extension(ef.create_extension("extendedKeyUsage","clientAuth,serverAuth,codeSigning,emailProtection",false))
      cert.sign cakey, OpenSSL::Digest::SHA256.new

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants