Skip to content

Commit 33be96b

Browse files
committed
XSI-1918: Host can not join pool after enable external auth
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. Signed-off-by: Lin Liu <[email protected]>
1 parent d27a118 commit 33be96b

File tree

3 files changed

+118
-17
lines changed

3 files changed

+118
-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: 105 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,91 @@ 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+
open Xapi_stdext_unix.Unixext
1420+
1421+
let path = "/etc/resolv.conf"
1422+
1423+
type t = Add | Remove
1424+
1425+
let handle op domain =
1426+
let config = Printf.sprintf "search %s" domain in
1427+
read_lines ~path |> List.filter (fun x -> x <> config) |> fun x ->
1428+
(match op with Add -> config :: x | Remove -> x) |> fun x ->
1429+
x @ [""] |> String.concat "\n" |> write_string_to_file path
1430+
1431+
let join ~domain = handle Add domain
1432+
1433+
let leave ~domain = handle Remove domain
1434+
end
1435+
1436+
module DNSSync = struct
1437+
let task_name = "Sync hostname with DNS"
1438+
1439+
type t = Register | Unregister
1440+
1441+
let handle op hostname netbios_name domain =
1442+
(* By default, hostname should equal to netbios_name, just register it to DNS server*)
1443+
try
1444+
let ops =
1445+
match op with Register -> "register" | Unregister -> "unregister"
1446+
in
1447+
let netbios_fqdn = Printf.sprintf "%s.%s" netbios_name domain in
1448+
let args = ["ads"; "dns"] @ [ops] @ ["--machine-pass"] in
1449+
Helpers.call_script net_cmd (args @ [netbios_fqdn]) |> ignore ;
1450+
if hostname <> netbios_name then
1451+
let hostname_fqdn = Printf.sprintf "%s.%s" hostname domain in
1452+
(* netbios_name is compressed, op on extra hostname *)
1453+
Helpers.call_script net_cmd (args @ [hostname_fqdn]) |> ignore
1454+
with e ->
1455+
debug "Register/unregister with DNS failed %s" (ExnHelper.string_of_exn e)
1456+
1457+
let register hostname netbios_name domain =
1458+
handle Register hostname netbios_name domain
1459+
1460+
let unregister hostname netbios_name domain =
1461+
handle Unregister hostname netbios_name domain
1462+
1463+
let sync () =
1464+
Server_helpers.exec_with_new_task "sync hostname with DNS"
1465+
@@ fun __context ->
1466+
let host = Helpers.get_localhost ~__context in
1467+
let service_name =
1468+
Db.Host.get_external_auth_service_name ~__context ~self:host
1469+
in
1470+
let netbios_name =
1471+
Db.Host.get_external_auth_configuration ~__context ~self:host
1472+
|> fun config -> List.assoc_opt "netbios_name" config
1473+
in
1474+
let hostname = Db.Host.get_hostname ~__context ~self:host in
1475+
match netbios_name with
1476+
| Some netbios ->
1477+
register hostname netbios service_name
1478+
| None ->
1479+
debug "Netbios name is none, skip sync hostname to DNS"
1480+
1481+
let trigger_sync ~start =
1482+
debug "Trigger task: %s" task_name ;
1483+
Scheduler.add_to_queue task_name
1484+
(Scheduler.Periodic !Xapi_globs.winbind_dns_sync_interval) start sync
1485+
1486+
let stop_sync () = Scheduler.remove_from_queue task_name
1487+
end
1488+
14011489
let build_netbios_name ~config_params =
14021490
let key = "netbios-name" in
14031491
match List.assoc_opt key config_params with
@@ -1721,20 +1809,24 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17211809
ClosestKdc.trigger_update ~start:0. ;
17221810
RotateMachinePassword.trigger_rotate ~start:0. ;
17231811
ConfigHosts.join ~domain:service_name ~name:netbios_name ;
1812+
ResolveConfig.join ~domain:service_name ;
1813+
DNSSync.trigger_sync ~start:0. ;
17241814
Winbind.set_machine_account_encryption_type netbios_name ;
17251815
debug "Succeed to join domain %s" service_name
17261816
with
17271817
| Forkhelpers.Spawn_internal_error (_, stdout, _) ->
17281818
error "Join domain: %s error: %s" service_name stdout ;
17291819
clear_winbind_config () ;
17301820
ConfigHosts.leave ~domain:service_name ~name:netbios_name ;
1821+
ResolveConfig.leave ~domain:service_name ;
17311822
(* The configure is kept for debug purpose with max level *)
17321823
raise (Auth_service_error (stdout |> tag_from_err_msg, stdout))
17331824
| Xapi_systemctl.Systemctl_fail _ ->
17341825
let msg = Printf.sprintf "Failed to start %s" Winbind.name in
17351826
error "Start daemon error: %s" msg ;
17361827
config_winbind_daemon ~domain:None ~workgroup:None ~netbios_name:None ;
17371828
ConfigHosts.leave ~domain:service_name ~name:netbios_name ;
1829+
ResolveConfig.leave ~domain:service_name ;
17381830
raise (Auth_service_error (E_GENERIC, msg))
17391831
| e ->
17401832
let msg =
@@ -1746,6 +1838,7 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17461838
error "Enable extauth error: %s" msg ;
17471839
clear_winbind_config () ;
17481840
ConfigHosts.leave ~domain:service_name ~name:netbios_name ;
1841+
ResolveConfig.leave ~domain:service_name ;
17491842
raise (Auth_service_error (E_GENERIC, msg))
17501843

17511844
(* unit on_disable()
@@ -1760,9 +1853,13 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17601853
let user = List.assoc_opt "user" config_params in
17611854
let pass = List.assoc_opt "pass" config_params in
17621855
let {service_name; netbios_name; _} = get_domain_info_from_db () in
1856+
ResolveConfig.leave ~domain:service_name ;
1857+
DNSSync.stop_sync () ;
17631858
( match netbios_name with
1764-
| Some name ->
1765-
ConfigHosts.leave ~domain:service_name ~name
1859+
| Some netbios ->
1860+
ConfigHosts.leave ~domain:service_name ~name:netbios ;
1861+
let hostname = get_localhost_name () in
1862+
DNSSync.unregister hostname netbios service_name
17661863
| _ ->
17671864
()
17681865
) ;
@@ -1792,6 +1889,7 @@ module AuthADWinbind : Auth_signature.AUTH_MODULE = struct
17921889
ClosestKdc.trigger_update ~start:ClosestKdc.startup_delay ;
17931890
RotateMachinePassword.trigger_rotate ~start:5. ;
17941891
Winbind.check_ready_to_serve ~timeout:300. ;
1892+
DNSSync.trigger_sync ~start:5. ;
17951893

17961894
let {service_name; netbios_name; _} = get_domain_info_from_db () in
17971895
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)