chef / knife-windows

Plugin for Chef's knife tool for working with Windows nodes
Apache License 2.0
152 stars 110 forks source link

Can't bootstrap windows node via winrm with cyrillic username #424

Closed jugatsu closed 5 years ago

jugatsu commented 7 years ago

I try to bootstrap node with cyrillic username

knife bootstrap windows winrm -m 1.1.1.1 -x Администратор -N 1c -P Secterpass122 -N node01

but got auth error

Response: WinRM::WinRMAuthorizationError
Hint: Make sure to prefix domain usernames with the correct domain name.
Hint: Local user names should be prefixed with computer name or IP address.
EXAMPLE: my_domain\user_namer
..ERROR: Failed to authenticate to 1.1.1.1 as Администратор

If i create user admin, i can bootstrap node without any issues.

Администратор == Administrator. This is default admin user for russian version of windows server.

mwrock commented 7 years ago

Out of curiosity, are you able to connect under this account using native powershell remoting via enter-pssession?

jugatsu commented 7 years ago

@mwrock Yes. I can connect throw enter-pssession. How can I debug further?

mwrock commented 7 years ago

I would try running a basic command in irb:

require 'winrm'
opts = { 
  endpoint: 'http://myhost:5985/wsman',
  user: 'Администратор',
  password: 'Pass@word1'
}
conn = WinRM::Connection.new(opts)
conn.shell(:powershell) do |shell|
  output = shell.run('$PSVersionTable') do |stdout, stderr|
    STDOUT.print stdout
    STDERR.print stderr
  end
  puts "The script exited with exit code #{output.exitcode}"
end

This should at least isolate if its a winrm gem or knife-windows issue.

Also would be helpful to know what version of windows you are connecting to.

jugatsu commented 7 years ago
ak@ak-pc:~/code$ ruby winrm.rb
/home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/http/response_handler.rb:58:in `raise_if_auth_error': WinRM::WinRMAuthorizationError (WinRM::WinRMAuthorizationError)
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/http/response_handler.rb:51:in `raise_if_error'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/http/response_handler.rb:36:in `parse_to_xml'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/http/transport.rb:186:in `send_request'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/http/transport.rb:181:in `send_request'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/shells/power_shell.rb:152:in `max_envelope_size_kb'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/shells/power_shell.rb:80:in `max_fragment_blob_size'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/shells/power_shell.rb:198:in `fragmenter'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/shells/power_shell.rb:162:in `block in open_shell_payload'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/shells/power_shell.rb:161:in `map'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/shells/power_shell.rb:161:in `open_shell_payload'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/shells/power_shell.rb:122:in `open_shell'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/shells/base.rb:163:in `block in open'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/shells/retryable.rb:37:in `retryable'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/shells/base.rb:161:in `open'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/shells/base.rb:124:in `with_command_shell'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/shells/base.rb:80:in `run'
    from winrm.rb:9:in `block in <main>'
    from /home/ak/.chefdk/gem/ruby/2.3.0/gems/winrm-2.1.1/lib/winrm/connection.rb:43:in `shell'
    from winrm.rb:8:in `<main>'

Windows Server 2012R2.

I'm debugging with eventlog and wireshark right now.

mwrock commented 7 years ago

ok well that should isolate it to either the winrm or rubyntlm gem. Try authenticating with basic authentication to rule out NTLM:

WinRM::Connection.new( 
  endpoint: 'http://myhost:5985/wsman',
  transport: :plaintext,
  user: 'Администратор',
  password: 'Pass@word1',
  basic_auth_only: true
)
mwrock commented 7 years ago

you will need to enable basic auth on the node for the above to work:

winrm set winrm/config/client/auth '@{Basic="true"}'
winrm set winrm/config/service/auth '@{Basic="true"}'
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
jugatsu commented 7 years ago

I dumped two winrm sessions. First one

 Enter-PSSession -ComputerName 1.1.1.1 -Credential $cred -Authentication Basic

and decoding of basic string

ak@ak-pc:~/code$ echo wOTs6O3o8fLw4PLu8DpBSWN0c29henAyUldrOWFLZA== | base64 -d
�������������:AIctsoazp2RWk9aKdak@ak-pc:~/code$

The second one from ruby script

ak@ak-pc:~/code$ cat winrm.rb 
require 'winrm'
opts = {
  endpoint: 'http://1.1.1.1:5985/wsman',
  transport: :plaintext,
  user: 'Администратор',
  password: 'AIctsoazp2RWk9aKd',
  basic_auth_only: true
}
conn = WinRM::Connection.new(opts)
conn.shell(:powershell) do |shell|
  output = shell.run('$PSVersionTable') do |stdout, stderr|
    STDOUT.print stdout
    STDERR.print stderr
  end
  puts "The script exited with exit code #{output.exitcode}"
end

here is decoding

ak@ak-pc:~/code$ echo 0JDQtNC80LjQvdC40YHRgtGA0LDRgtC+0YA6QUljdHNvYXpwMlJXazlhS2Q= | base64 -d
Администратор:AIctsoazp2RWk9aKdak@ak-pc:~/code$
jugatsu commented 7 years ago

The same error.

jugatsu commented 7 years ago

OS: WIndows Server 2012R2 Russian, codepage 866

mwrock commented 7 years ago

another thing to try is changing the codepage shell options: --winrm-codepage 866 in the knife command.

jugatsu commented 7 years ago

Doesn't work. The same error from bootstrap. Also i can't debug bootstrap command with --winrm-authentication-protocol basic Get warning

ERROR: Validatorless bootstrap over unsecure winrm channels could expose your key to network sniffing

Maybe the issue in Locale and DataLocale from XML envelope. ru-RU vs en-US

jugatsu commented 7 years ago

I think the issue is that enter-pssession send credentials in windows-1251. As opposite to ruby-winrm which send in utf-8.

jugatsu commented 7 years ago

http://foxtools.ru/Base64 you can paste wOTs6O3o8fLw4PLu8DpBSWN0c29henAyUldrOWFLZA== and will get result in cp1251

jugatsu commented 7 years ago

Also try with --winrm-codepage 1251.

jugatsu commented 7 years ago

with admin it works as expected

ak@ak-pc:~/code$ ruby winrm.rb

Name                           Value                                           
----                           -----                                           
PSVersion                      5.0.10586.117                                   
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                         
BuildVersion                   10.0.10586.117                                  
CLRVersion                     4.0.30319.42000                                 
WSManStackVersion              3.0                                             
PSRemotingProtocolVersion      2.3                                             
SerializationVersion           1.1.0.1                                         

The script exited with exit code 0
mwrock commented 7 years ago

hmm. maybe we need to encode creds with windows-1251

jugatsu commented 7 years ago

@mwrock Yep.

require 'winrm'
username = 'Администратор'.encode('windows-1251')
puts username

opts = {
  endpoint: 'http://1.1.1.1:5985/wsman',
  transport: :plaintext,
  user: username.to_s,
  password: 'AIctsoazp2RWk9aKd',
  basic_auth_only: true,
}
conn = WinRM::Connection.new(opts)
conn.shell(:powershell) do |shell|
  output = shell.run('$PSVersionTable') do |stdout, stderr|
    STDOUT.print stdout
    STDERR.print stderr
  end
  puts "The script exited with exit code #{output.exitcode}"
end

output

ak@ak-pc:~/code$ ruby winrm.rb
������������

Name                           Value                                           
----                           -----                                           
PSVersion                      5.0.10586.117                                   
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                         
BuildVersion                   10.0.10586.117                                  
CLRVersion                     4.0.30319.42000                                 
WSManStackVersion              3.0                                             
PSRemotingProtocolVersion      2.3                                             
SerializationVersion           1.1.0.1                                         

The script exited with exit code 0
mwrock commented 7 years ago

great! Then this is easily fixable. I can get a dev winrm gem out in the next hour to test.

mwrock commented 7 years ago

I ended up not being able to access the russian language packs due to my subscription level. Simply adding a user with russian characters work but I cant authenticate that user even via native powershell remoting. I can only auth via remote desktop. Some other testing shows that converting to windows-1251 breaks some rubyntlm and negotiate auth.

I'm happy to take in PRs to winrm if you find a fix that for your environment.

jugatsu commented 7 years ago

@mwrock thx a lot for helping debugging. I don't think i can make PR right now.

Vasu1105 commented 5 years ago

@tas50 / @btm From overall conversation it looks like this bug is in winrm should we close this from here and open this in winrm ?

btm commented 5 years ago

@Vasu1105 this would have been an issue with how we were encoding the string with knife-windows.

However as of Chef Infra 15 (and knife-windows v3) bootstrap support for windows is in the core Chef Infra client now and uses train as a transport. If anyone experiences this issue going forward, the bug will likely be against Chef or https://github.com/inspec/train instead.