Skip to content

Commit 35c353c

Browse files
authored
XSI-1918: Host can not join pool after enable external auth (#6492)
commit 6ac37d7 add localhost name to /etc/hosts There problem is, instead of appending FQDN to the end of the line, the entry should in following format: IP FQDN [alias1] [alias2] Besides, another non-regression is found. The host need to change its static IP and DNS to join AD, However, then the Host record is not send to DNS, cause the pool member can not resovle each other. To resovle the issue, a task is scheduled to sync the hostname to DNS.
2 parents c3761f9 + cba2f1d commit 35c353c

File tree

3 files changed

+117
-17
lines changed

3 files changed

+117
-17
lines changed

ocaml/tests/test_extauth_plugin_ADwinbind.ml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -517,17 +517,17 @@ let test_add_ipv4_localhost_to_hosts =
517517
localhost4.localdomain4"
518518
]
519519
, [
520-
"127.0.0.1 localhost localhost.localdomain localhost4 \
521-
localhost4.localdomain4 hostname hostname.domain"
520+
"127.0.0.1 hostname.domain hostname localhost \
521+
localhost.localdomain localhost4 localhost4.localdomain4"
522522
]
523523
)
524524
; ( ["127.0.0.1 localhost hostname hostname.domain localhost.localdomain"]
525-
, ["127.0.0.1 localhost localhost.localdomain hostname hostname.domain"]
525+
, ["127.0.0.1 hostname.domain hostname localhost localhost.localdomain"]
526526
)
527527
; ( ["192.168.0.1 some_host"]
528-
, ["127.0.0.1 hostname hostname.domain"; "192.168.0.1 some_host"]
528+
, ["127.0.0.1 hostname.domain hostname"; "192.168.0.1 some_host"]
529529
)
530-
; ([], ["127.0.0.1 hostname hostname.domain"])
530+
; ([], ["127.0.0.1 hostname.domain hostname"])
531531
]
532532
in
533533
matrix |> List.map @@ fun (inp, exp) -> ("<omit inp>", `Quick, check inp exp)
@@ -549,18 +549,18 @@ let test_add_ipv4_and_ipv6_localhost_to_hosts =
549549
[
550550
( ["127.0.0.1 localhost"]
551551
, [
552-
"::1 hostname hostname.domain"
553-
; "127.0.0.1 localhost hostname hostname.domain"
552+
"::1 hostname.domain hostname"
553+
; "127.0.0.1 hostname.domain hostname localhost"
554554
]
555555
)
556556
; ( ["127.0.0.1 localhost"; "::1 localhost"]
557557
, [
558-
"127.0.0.1 localhost hostname hostname.domain"
559-
; "::1 localhost hostname hostname.domain"
558+
"127.0.0.1 hostname.domain hostname localhost"
559+
; "::1 hostname.domain hostname localhost"
560560
]
561561
)
562562
; ( []
563-
, ["127.0.0.1 hostname hostname.domain"; "::1 hostname hostname.domain"]
563+
, ["127.0.0.1 hostname.domain hostname"; "::1 hostname.domain hostname"]
564564
)
565565
]
566566
in

ocaml/xapi/extauth_plugin_ADwinbind.ml

Lines changed: 104 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,13 +1347,28 @@ module HostsConfFunc (T : LocalHostTag) : HostsConf = struct
13471347
let name = String.lowercase_ascii name in
13481348
let domain = String.lowercase_ascii domain in
13491349
let fqdn = Printf.sprintf "%s.%s" name domain in
1350+
let rec add_hostname pre line =
1351+
match line with
1352+
| ip :: alias when ip = T.local_ip ->
1353+
(* Add localhost IP *)
1354+
add_hostname [ip] alias
1355+
| sp :: left when sp = "" ->
1356+
(* Add space to reserve the indent *)
1357+
add_hostname (pre @ [sp]) left
1358+
| alias :: left ->
1359+
(* hosts entry: ip fqdn alias1 alias2 ... *)
1360+
pre @ [fqdn; name; alias] @ left
1361+
| [] ->
1362+
failwith "Can not add local hostname to non local IP"
1363+
in
1364+
13501365
match interest line with
13511366
| false ->
13521367
line
13531368
| true ->
13541369
String.split_on_char sep line
13551370
|> List.filter (fun x -> x <> name && x <> fqdn)
1356-
|> (fun x -> match op with Add -> x @ [name; fqdn] | Remove -> x)
1371+
|> (fun x -> match op with Add -> add_hostname [] x | Remove -> x)
13571372
|> String.concat sep_str
13581373

13591374
let leave ~name ~domain ~lines =
@@ -1369,8 +1384,8 @@ module HostsConfFunc (T : LocalHostTag) : HostsConf = struct
13691384
| false ->
13701385
(* Does not found and updated the conf, then add one *)
13711386
[
1372-
Printf.sprintf "%s%s%s%s%s.%s" T.local_ip sep_str name sep_str name
1373-
domain
1387+
Printf.sprintf "%s%s%s.%s%s%s" T.local_ip sep_str name domain sep_str
1388+
name
13741389
]
13751390
@ x
13761391
end
@@ -1386,18 +1401,90 @@ module ConfigHosts = struct
13861401
let join ~name ~domain =
13871402
read_lines ~path |> fun lines ->
13881403
HostsConfIPv4.join ~name ~domain ~lines |> fun lines ->
1389-
HostsConfIPv6.join ~name ~domain ~lines
1404+
HostsConfIPv6.join ~name ~domain ~lines |> fun x ->
1405+
x @ [""] (* Add final line break *)
13901406
|> String.concat "\n"
13911407
|> write_string_to_file path
13921408

13931409
let leave ~name ~domain =
13941410
read_lines ~path |> fun lines ->
13951411
HostsConfIPv4.leave ~name ~domain ~lines |> fun lines ->
1396-
HostsConfIPv6.leave ~name ~domain ~lines
1412+
HostsConfIPv6.leave ~name ~domain ~lines |> fun x ->
1413+
x @ [""] (* Add final line break *)
13971414
|> String.concat "\n"
13981415
|> write_string_to_file path
13991416
end
14001417

1418+
module ResolveConfig = struct
1419+
let path = "/etc/resolv.conf"
1420+
1421+
type t = Add | Remove
1422+
1423+
let handle op domain =
1424+
let open Xapi_stdext_unix.Unixext in
1425+
let config = Printf.sprintf "search %s" domain in
1426+
read_lines ~path |> List.filter (fun x -> x <> config) |> fun x ->
1427+
(match op with Add -> config :: x | Remove -> x) |> fun x ->
1428+
x @ [""] |> String.concat "\n" |> write_string_to_file path
1429+
1430+
let join ~domain = handle Add domain
1431+
1432+
let leave ~domain = handle Remove domain
1433+
end
1434+
1435+
module DNSSync = struct
1436+
let task_name = "Sync hostname with DNS"
1437+
1438+
type t = Register | Unregister
1439+
1440+
let handle op hostname netbios_name domain =
1441+
(* By default, hostname should equal to netbios_name, just register it to DNS server*)
1442+
try
1443+
let ops =
1444+
match op with Register -> "register" | Unregister -> "unregister"
1445+
in
1446+
let netbios_fqdn = Printf.sprintf "%s.%s" netbios_name domain in
1447+
let args = ["ads"; "dns"] @ [ops] @ ["--machine-pass"] in
1448+
Helpers.call_script net_cmd (args @ [netbios_fqdn]) |> ignore ;
1449+
if hostname <> netbios_name then
1450+
let hostname_fqdn = Printf.sprintf "%s.%s" hostname domain in
1451+
(* netbios_name is compressed, op on extra hostname *)
1452+
Helpers.call_script net_cmd (args @ [hostname_fqdn]) |> ignore
1453+
with e ->
1454+
debug "Register/unregister with DNS failed %s" (ExnHelper.string_of_exn e)
1455+
1456+
let register hostname netbios_name domain =
1457+
handle Register hostname netbios_name domain
1458+
1459+
let unregister hostname netbios_name domain =
1460+
handle Unregister hostname netbios_name domain
1461+
1462+
let sync () =
1463+
Server_helpers.exec_with_new_task "sync hostname with DNS"
1464+
@@ fun __context ->
1465+
let host = Helpers.get_localhost ~__context in
1466+
let service_name =
1467+
Db.Host.get_external_auth_service_name ~__context ~self:host
1468+
in
1469+
let netbios_name =
1470+
Db.Host.get_external_auth_configuration ~__context ~self:host
1471+
|> fun config -> List.assoc_opt "netbios_name" config
1472+
in
1473+
let hostname = Db.Host.get_hostname ~__context ~self:host in
1474+
match netbios_name with
1475+
| Some netbios ->
1476+
register hostname netbios service_name
1477+
| None ->
1478+
debug "Netbios name is none, skip sync hostname to DNS"
1479+
1480+
let trigger_sync ~start =
1481+
debug "Trigger task: %s" task_name ;
1482+
Scheduler.add_to_queue task_name
1483+
(Scheduler.Periodic !Xapi_globs.winbind_dns_sync_interval) start sync
1484+
1485+
let stop_sync () = Scheduler.remove_from_queue task_name
1486+
end
1487+
14011488
let build_netbios_name ~config_params =
14021489
let key = "netbios-name" in
14031490
match List.assoc_opt key config_params with
@@ -1721,20 +1808,24 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17211808
ClosestKdc.trigger_update ~start:0. ;
17221809
RotateMachinePassword.trigger_rotate ~start:0. ;
17231810
ConfigHosts.join ~domain:service_name ~name:netbios_name ;
1811+
ResolveConfig.join ~domain:service_name ;
1812+
DNSSync.trigger_sync ~start:0. ;
17241813
Winbind.set_machine_account_encryption_type netbios_name ;
17251814
debug "Succeed to join domain %s" service_name
17261815
with
17271816
| Forkhelpers.Spawn_internal_error (_, stdout, _) ->
17281817
error "Join domain: %s error: %s" service_name stdout ;
17291818
clear_winbind_config () ;
17301819
ConfigHosts.leave ~domain:service_name ~name:netbios_name ;
1820+
ResolveConfig.leave ~domain:service_name ;
17311821
(* The configure is kept for debug purpose with max level *)
17321822
raise (Auth_service_error (stdout |> tag_from_err_msg, stdout))
17331823
| Xapi_systemctl.Systemctl_fail _ ->
17341824
let msg = Printf.sprintf "Failed to start %s" Winbind.name in
17351825
error "Start daemon error: %s" msg ;
17361826
config_winbind_daemon ~domain:None ~workgroup:None ~netbios_name:None ;
17371827
ConfigHosts.leave ~domain:service_name ~name:netbios_name ;
1828+
ResolveConfig.leave ~domain:service_name ;
17381829
raise (Auth_service_error (E_GENERIC, msg))
17391830
| e ->
17401831
let msg =
@@ -1746,6 +1837,7 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17461837
error "Enable extauth error: %s" msg ;
17471838
clear_winbind_config () ;
17481839
ConfigHosts.leave ~domain:service_name ~name:netbios_name ;
1840+
ResolveConfig.leave ~domain:service_name ;
17491841
raise (Auth_service_error (E_GENERIC, msg))
17501842

17511843
(* unit on_disable()
@@ -1760,9 +1852,13 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17601852
let user = List.assoc_opt "user" config_params in
17611853
let pass = List.assoc_opt "pass" config_params in
17621854
let {service_name; netbios_name; _} = get_domain_info_from_db () in
1855+
ResolveConfig.leave ~domain:service_name ;
1856+
DNSSync.stop_sync () ;
17631857
( match netbios_name with
1764-
| Some name ->
1765-
ConfigHosts.leave ~domain:service_name ~name
1858+
| Some netbios ->
1859+
ConfigHosts.leave ~domain:service_name ~name:netbios ;
1860+
let hostname = get_localhost_name () in
1861+
DNSSync.unregister hostname netbios service_name
17661862
| _ ->
17671863
()
17681864
) ;
@@ -1792,6 +1888,7 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17921888
ClosestKdc.trigger_update ~start:ClosestKdc.startup_delay ;
17931889
RotateMachinePassword.trigger_rotate ~start:5. ;
17941890
Winbind.check_ready_to_serve ~timeout:300. ;
1891+
DNSSync.trigger_sync ~start:5. ;
17951892

17961893
let {service_name; netbios_name; _} = get_domain_info_from_db () in
17971894
match netbios_name with

ocaml/xapi/xapi_globs.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,8 @@ let winbind_cache_time = ref 60
10171017

10181018
let winbind_machine_pwd_timeout = ref (2. *. 7. *. 24. *. 3600.)
10191019

1020+
let winbind_dns_sync_interval = ref 3600.
1021+
10201022
let winbind_update_closest_kdc_interval = ref (3600. *. 22.)
10211023
(* every 22 hours *)
10221024

@@ -1219,6 +1221,7 @@ let xapi_globs_spec =
12191221
; ("winbind_debug_level", Int winbind_debug_level)
12201222
; ("winbind_cache_time", Int winbind_cache_time)
12211223
; ("winbind_machine_pwd_timeout", Float winbind_machine_pwd_timeout)
1224+
; ("winbind_dns_sync_interval", Float winbind_dns_sync_interval)
12221225
; ( "winbind_update_closest_kdc_interval"
12231226
, Float winbind_update_closest_kdc_interval
12241227
)

0 commit comments

Comments
 (0)