Skip to content

Commit 492beb8

Browse files
committed
Improve join robustness
- Added detailed logging for better traceability - Improved error handling with specific methods for different error types - Introduced helper methods to reduce code duplication
1 parent bd3a949 commit 492beb8

File tree

1 file changed

+75
-10
lines changed

1 file changed

+75
-10
lines changed

lib/smart_proxy_realm_ad/provider.rb

+75-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# frozen_string_literal: true
2-
31
require 'proxy/kerberos'
42
require 'radcli'
53
require 'digest'
@@ -10,7 +8,7 @@ class Provider
108
include Proxy::Util
119
include Proxy::Kerberos
1210

13-
attr_reader :realm, :keytab_path, :principal, :domain_controller, :domain, :ou, :computername_prefix, :computername_hash, :computername_use_fqdn
11+
attr_reader :realm, :keytab_path, :principal, :domain_controller, :domain, :ou, :computername_prefix, :computername_hash, :computername_use_fqdn, :ignore_computername_exists
1412

1513
def initialize(options = {})
1614
@realm = options[:realm]
@@ -22,6 +20,7 @@ def initialize(options = {})
2220
@computername_prefix = options[:computername_prefix]
2321
@computername_hash = options[:computername_hash]
2422
@computername_use_fqdn = options[:computername_use_fqdn]
23+
@ignore_computername_exists = options.fetch(:ignore_computername_exists, false)
2524
logger.info 'Proxy::AdRealm: initialize...'
2625
end
2726

@@ -90,20 +89,25 @@ def radcli_connect
9089
# Connect to active directory
9190
conn = Adcli::AdConn.new(@domain)
9291
conn.set_domain_realm(@realm)
92+
# Directly connect to the domain controller if specified, skip the SRV lookup
9393
conn.set_domain_controller(@domain_controller) unless @domain_controller.nil?
9494
conn.set_login_ccache_name('')
9595
conn.connect
9696
conn
9797
end
9898

99+
MAX_RETRIES = 100
100+
RETRY_DELAY = 0.3
101+
99102
def radcli_join(hostfqdn, computername, password)
100-
# Join computer
101-
enroll = Adcli::AdEnroll.new(@adconn)
102-
enroll.set_computer_name(computername)
103-
enroll.set_host_fqdn(hostfqdn)
104-
enroll.set_domain_ou(@ou) if @ou
105-
enroll.set_computer_password(password)
106-
enroll.join
103+
enroll = setup_enroll(hostfqdn, computername, password)
104+
begin
105+
enroll.join
106+
logger.info "Successfully joined computer #{computername} with FQDN #{hostfqdn}"
107+
true
108+
rescue RuntimeError => ex
109+
handle_runtime_error(ex, enroll)
110+
end
107111
end
108112

109113
def generate_password
@@ -127,5 +131,66 @@ def radcli_delete(computername)
127131
enroll.set_domain_ou(@ou) if @ou
128132
enroll.delete
129133
end
134+
135+
private
136+
137+
def setup_enroll(hostfqdn, computername, password)
138+
enroll = Adcli::AdEnroll.new(@adconn)
139+
enroll.set_computer_name(computername)
140+
enroll.set_host_fqdn(hostfqdn)
141+
enroll.set_domain_ou(@ou) if @ou
142+
enroll.set_computer_password(password)
143+
enroll
144+
end
145+
146+
def handle_runtime_error(ex, enroll)
147+
if ex.message =~ /Authentication error/
148+
retry_authentication_error(enroll)
149+
elsif ex.message =~ /already exists/
150+
handle_already_exists_error
151+
else
152+
log_error("Failed to join computer: #{ex.message}")
153+
raise ex
154+
end
155+
end
156+
157+
def retry_authentication_error(enroll)
158+
MAX_RETRIES.times do |i|
159+
sleep(RETRY_DELAY)
160+
begin
161+
if enroll.respond_to?(:update)
162+
enroll.update
163+
else
164+
enroll.password
165+
end
166+
log_info("Successfully updated computer after authentication error")
167+
return true
168+
rescue RuntimeError => ex
169+
if i >= MAX_RETRIES - 1 || ex.message !~ /Authentication error/
170+
log_error("Failed to update computer after #{MAX_RETRIES} attempts: #{ex.message}")
171+
raise ex
172+
end
173+
end
174+
end
175+
end
176+
177+
def handle_already_exists_error
178+
if ignore_computername_exists
179+
log_info("Computer name already exists, but ignoring as per configuration")
180+
true
181+
else
182+
log_error("Computer name already exists and cannot proceed")
183+
raise "Computer name already exists"
184+
end
185+
end
186+
187+
def log_info(message)
188+
logger.info "Proxy::AdRealm: #{message}"
189+
end
190+
191+
def log_error(message)
192+
logger.error "Proxy::AdRealm: #{message}"
193+
end
194+
130195
end
131196
end

0 commit comments

Comments
 (0)