1 # Unix SMB/CIFS implementation.
3 # Tests for samba-tool domain auth policy command
5 # Copyright (C) Catalyst.Net Ltd. 2023
7 # Written by Rob van der Linde <rob@catalyst.net.nz>
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 3 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 from optparse
import OptionValueError
25 from unittest
.mock
import patch
27 from samba
.dcerpc
import security
28 from samba
.domain
.models
.exceptions
import ModelError
29 from samba
.ndr
import ndr_pack
, ndr_unpack
30 from samba
.nt_time
import NT_TICKS_PER_SEC
31 from samba
.samdb
import SamDB
32 from samba
.sd_utils
import SDUtils
34 from .silo_base
import SiloTest
37 def mins_to_tgt_lifetime(minutes
):
38 """Convert minutes to the tgt_lifetime attributes unit which is 10^-7 seconds"""
39 if minutes
is not None:
40 return minutes
* 60 * NT_TICKS_PER_SEC
43 class AuthPolicyCmdTestCase(SiloTest
):
46 """Test listing authentication policies in list format."""
47 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "list")
48 self
.assertIsNone(result
, msg
=err
)
50 expected_policies
= ["User Policy", "Service Policy", "Computer Policy"]
52 for policy
in expected_policies
:
53 self
.assertIn(policy
, out
)
55 def test_list__json(self
):
56 """Test listing authentication policies in JSON format."""
57 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
59 self
.assertIsNone(result
, msg
=err
)
61 # we should get valid json
62 policies
= json
.loads(out
)
64 expected_policies
= ["User Policy", "Service Policy", "Computer Policy"]
66 for name
in expected_policies
:
67 policy
= policies
[name
]
68 self
.assertIn("name", policy
)
69 self
.assertIn("msDS-AuthNPolicy", list(policy
["objectClass"]))
70 self
.assertIn("msDS-AuthNPolicyEnforced", policy
)
71 self
.assertIn("msDS-StrongNTLMPolicy", policy
)
72 self
.assertIn("objectGUID", policy
)
75 """Test viewing a single authentication policy."""
76 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "view",
77 "--name", "User Policy")
78 self
.assertIsNone(result
, msg
=err
)
80 # we should get valid json
81 policy
= json
.loads(out
)
83 # check a few fields only
84 self
.assertEqual(policy
["cn"], "User Policy")
85 self
.assertEqual(policy
["msDS-AuthNPolicyEnforced"], True)
87 def test_view__notfound(self
):
88 """Test viewing an authentication policy that doesn't exist."""
89 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "view",
90 "--name", "doesNotExist")
91 self
.assertEqual(result
, -1)
92 self
.assertIn("Authentication policy doesNotExist not found.", err
)
94 def test_view__name_required(self
):
95 """Test view authentication policy without --name argument."""
96 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "view")
97 self
.assertEqual(result
, -1)
98 self
.assertIn("Argument --name is required.", err
)
100 def test_create__success(self
):
101 """Test creating a new authentication policy."""
102 name
= self
.unique_name()
104 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
105 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
107 self
.assertIsNone(result
, msg
=err
)
109 # Check policy that was created
110 policy
= self
.get_authentication_policy(name
)
111 self
.assertEqual(str(policy
["cn"]), name
)
112 self
.assertEqual(str(policy
["msDS-AuthNPolicyEnforced"]), "TRUE")
114 def test_create__description(self
):
115 """Test creating a new authentication policy with description set."""
116 name
= self
.unique_name()
118 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
119 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
121 "--description", "Custom Description")
122 self
.assertIsNone(result
, msg
=err
)
124 # Check policy description
125 policy
= self
.get_authentication_policy(name
)
126 self
.assertEqual(str(policy
["cn"]), name
)
127 self
.assertEqual(str(policy
["description"]), "Custom Description")
129 def test_create__user_tgt_lifetime_mins(self
):
130 """Test create a new authentication policy with --user-tgt-lifetime-mins.
132 Also checks the upper and lower bounds are handled.
134 name
= self
.unique_name()
136 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
137 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
139 "--user-tgt-lifetime-mins", "60")
140 self
.assertIsNone(result
, msg
=err
)
142 # Check policy fields.
143 policy
= self
.get_authentication_policy(name
)
144 self
.assertEqual(str(policy
["cn"]), name
)
145 self
.assertEqual(str(policy
["msDS-UserTGTLifetime"]), str(mins_to_tgt_lifetime(60)))
147 # check lower bounds (45)
148 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
149 "--name", name
+ "Lower",
150 "--user-tgt-lifetime-mins", "44")
151 self
.assertEqual(result
, -1)
152 self
.assertIn("--user-tgt-lifetime-mins must be between 45 and 2147483647",
155 # check upper bounds (2147483647)
156 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
157 "--name", name
+ "Upper",
158 "--user-tgt-lifetime-mins", "2147483648")
159 self
.assertEqual(result
, -1)
160 self
.assertIn("--user-tgt-lifetime-mins must be between 45 and 2147483647",
163 def test_create__service_tgt_lifetime_mins(self
):
164 """Test create a new authentication policy with --service-tgt-lifetime-mins.
166 Also checks the upper and lower bounds are handled.
168 name
= self
.unique_name()
170 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
171 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
173 "--service-tgt-lifetime-mins", "60")
174 self
.assertIsNone(result
, msg
=err
)
176 # Check policy fields.
177 policy
= self
.get_authentication_policy(name
)
178 self
.assertEqual(str(policy
["cn"]), name
)
179 self
.assertEqual(str(policy
["msDS-ServiceTGTLifetime"]), str(mins_to_tgt_lifetime(60)))
181 # check lower bounds (45)
182 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
184 "--service-tgt-lifetime-mins", "44")
185 self
.assertEqual(result
, -1)
186 self
.assertIn("--service-tgt-lifetime-mins must be between 45 and 2147483647",
189 # check upper bounds (2147483647)
190 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
192 "--service-tgt-lifetime-mins", "2147483648")
193 self
.assertEqual(result
, -1)
194 self
.assertIn("--service-tgt-lifetime-mins must be between 45 and 2147483647",
197 def test_create__computer_tgt_lifetime_mins(self
):
198 """Test create a new authentication policy with --computer-tgt-lifetime-mins.
200 Also checks the upper and lower bounds are handled.
202 name
= self
.unique_name()
204 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
205 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
207 "--computer-tgt-lifetime-mins", "60")
208 self
.assertIsNone(result
, msg
=err
)
210 # Check policy fields.
211 policy
= self
.get_authentication_policy(name
)
212 self
.assertEqual(str(policy
["cn"]), name
)
213 self
.assertEqual(str(policy
["msDS-ComputerTGTLifetime"]), str(mins_to_tgt_lifetime(60)))
215 # check lower bounds (45)
216 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
217 "--name", name
+ "Lower",
218 "--computer-tgt-lifetime-mins", "44")
219 self
.assertEqual(result
, -1)
220 self
.assertIn("--computer-tgt-lifetime-mins must be between 45 and 2147483647",
223 # check upper bounds (2147483647)
224 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
225 "--name", name
+ "Upper",
226 "--computer-tgt-lifetime-mins", "2147483648")
227 self
.assertEqual(result
, -1)
228 self
.assertIn("--computer-tgt-lifetime-mins must be between 45 and 2147483647",
231 def test_create__valid_sddl(self
):
232 """Test creating a new authentication policy with valid SDDL in a field."""
233 name
= self
.unique_name()
234 expected
= "O:SYG:SYD:(XA;OICI;CR;;;WD;(Member_of {SID(AO)}))"
236 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
237 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
239 "--user-allowed-to-authenticate-from",
241 self
.assertIsNone(result
, msg
=err
)
243 # Check policy fields.
244 policy
= self
.get_authentication_policy(name
)
245 self
.assertEqual(str(policy
["cn"]), name
)
246 desc
= policy
["msDS-UserAllowedToAuthenticateFrom"][0]
247 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
248 self
.assertEqual(sddl
, expected
)
250 def test_create__invalid_sddl(self
):
251 """Test creating a new authentication policy with invalid SDDL in a field."""
252 name
= self
.unique_name()
254 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
256 "--user-allowed-to-authenticate-from",
259 self
.assertEqual(result
, -1)
260 self
.assertIn("Unable to parse SDDL", err
)
261 self
.assertIn(" *INVALID SDDL*\n ^\n expected '[OGDS]:' section start ", err
)
263 def test_create__invalid_sddl_conditional_ace(self
):
264 """Test creating a new authentication policy with invalid SDDL in a field."""
265 sddl
= "O:SYG:SYD:(XA;OICI;CR;;;WD;(Member_of {secret club}))"
266 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
267 "--name", "invalidSDDLPolicy2",
268 "--user-allowed-to-authenticate-from",
270 self
.assertEqual(result
, -1)
271 self
.assertIn("Unable to parse SDDL", err
)
272 self
.assertIn(sddl
, err
)
273 self
.assertIn(f
"\n{'^':>41}", err
)
274 self
.assertIn("unexpected byte 0x73 's' parsing literal", err
)
275 self
.assertNotIn(" File ", err
)
277 def test_create__invalid_sddl_conditional_ace_non_ascii(self
):
278 """Test creating a new authentication policy with invalid SDDL in a field."""
279 sddl
= 'O:SYG:SYD:(XA;OICI;CR;;;WD;(@User.āāēē == "łē¶ŧ¹⅓þōīŋ“đ¢ð»" && Member_of {secret club}))'
280 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
281 "--name", "invalidSDDLPolicy2",
282 "--user-allowed-to-authenticate-from",
284 self
.assertEqual(result
, -1)
285 self
.assertIn("Unable to parse SDDL", err
)
286 self
.assertIn(sddl
, err
)
287 self
.assertIn(f
"\n{'^':>76}\n", err
)
288 self
.assertIn(" unexpected byte 0x73 's' parsing literal", err
)
289 self
.assertNotIn(" File ", err
)
291 def test_create__invalid_sddl_normal_ace(self
):
292 """Test creating a new authentication policy with invalid SDDL in a field."""
293 sddl
= "O:SYG:SYD:(A;;;;ZZ)(XA;OICI;CR;;;WD;(Member_of {WD}))"
294 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
295 "--name", "invalidSDDLPolicy3",
296 "--user-allowed-to-authenticate-from",
298 self
.assertEqual(result
, -1)
299 self
.assertIn("Unable to parse SDDL", err
)
300 self
.assertIn(sddl
, err
)
301 self
.assertIn(f
"\n{'^':>13}", err
)
302 self
.assertIn("\n malformed ACE with only 4 ';'\n", err
)
303 self
.assertNotIn(" File ", err
) # traceback marker
305 def test_create__device_attribute_in_sddl_allowed_to(self
):
306 """Test creating a new authentication policy that uses
307 user-allowed-to-authenticate-to with a device attribute."""
309 sddl
= 'O:SYG:SYD:(XA;OICI;CR;;;WD;(@Device.claim == "foo"))'
311 name
= self
.unique_name()
312 self
.addCleanup(self
.delete_authentication_policy
, name
=name
)
313 result
, _
, err
= self
.runcmd("domain", "auth", "policy", "create",
315 "--user-allowed-to-authenticate-to",
317 self
.assertIsNone(result
, msg
=err
)
319 def test_create__device_operator_in_sddl_allowed_to(self
):
320 """Test creating a new authentication policy that uses
321 user-allowed-to-authenticate-to with a device operator."""
323 sddl
= 'O:SYG:SYD:(XA;OICI;CR;;;WD;(Not_Device_Member_of {SID(WD)}))'
325 name
= self
.unique_name()
326 self
.addCleanup(self
.delete_authentication_policy
, name
=name
)
327 result
, _
, err
= self
.runcmd("domain", "auth", "policy", "create",
329 "--user-allowed-to-authenticate-to",
331 self
.assertIsNone(result
, msg
=err
)
333 def test_create__device_attribute_in_sddl_allowed_from(self
):
334 """Test creating a new authentication policy that uses
335 user-allowed-to-authenticate-from with a device attribute."""
337 sddl
= 'O:SYG:SYD:(XA;OICI;CR;;;WD;(@Device.claim == "foo"))'
339 name
= self
.unique_name()
340 result
, _
, err
= self
.runcmd("domain", "auth", "policy", "create",
342 "--user-allowed-to-authenticate-from",
344 self
.assertEqual(result
, -1)
345 self
.assertIn("Unable to parse SDDL", err
)
346 self
.assertIn(sddl
, err
)
347 self
.assertIn(f
"\n{'^':>31}\n", err
)
348 self
.assertIn(" a device attribute is not applicable in this context "
349 "(did you intend a user attribute?)",
351 self
.assertNotIn(" File ", err
)
353 def test_create__device_operator_in_sddl_allowed_from(self
):
354 """Test creating a new authentication policy that uses
355 user-allowed-to-authenticate-from with a device operator."""
357 sddl
= 'O:SYG:SYD:(XA;OICI;CR;;;WD;(Not_Device_Member_of {SID(WD)}))'
359 name
= self
.unique_name()
360 result
, _
, err
= self
.runcmd("domain", "auth", "policy", "create",
362 "--user-allowed-to-authenticate-from",
364 self
.assertEqual(result
, -1)
365 self
.assertIn("Unable to parse SDDL", err
)
366 self
.assertIn(sddl
, err
)
367 self
.assertIn(f
"\n{'^':>30}\n", err
)
368 self
.assertIn(" a device‐relative expression will never evaluate to "
369 "true in this context (did you intend a user‐relative "
372 self
.assertNotIn(" File ", err
)
374 def test_create__device_attribute_in_sddl_already_exists(self
):
375 """Test modifying an existing authentication policy that uses
376 user-allowed-to-authenticate-from with a device attribute."""
378 # The SDDL refers to ‘Device.claim’.
379 sddl
= 'O:SYG:SYD:(XA;OICI;CR;;;WD;(@Device.claim == "foo"))'
380 domain_sid
= security
.dom_sid(self
.samdb
.get_domain_sid())
381 descriptor
= security
.descriptor
.from_sddl(sddl
, domain_sid
)
383 # Manually create an authentication policy that refers to a device
386 name
= self
.unique_name()
387 dn
= self
.get_authn_policies_dn()
388 dn
.add_child(f
"CN={name}")
391 'msDS-AuthNPolicyEnforced': b
'TRUE',
392 'objectClass': b
'msDS-AuthNPolicy',
393 'msDS-UserAllowedToAuthenticateFrom': ndr_pack(descriptor
),
396 self
.addCleanup(self
.delete_authentication_policy
, name
=name
)
397 self
.samdb
.add(message
)
399 # Change the policy description. This should succeed, in spite of the
400 # policy’s referring to a device attribute when it shouldn’t.
401 result
, _
, err
= self
.runcmd("domain", "auth", "policy", "modify",
403 "--description", "NewDescription")
404 self
.assertIsNone(result
, msg
=err
)
406 def test_create__already_exists(self
):
407 """Test creating a new authentication policy that already exists."""
408 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
409 "--name", "User Policy")
410 self
.assertEqual(result
, -1)
411 self
.assertIn("Authentication policy User Policy already exists", err
)
413 def test_create__name_missing(self
):
414 """Test create authentication policy without --name argument."""
415 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create")
416 self
.assertEqual(result
, -1)
417 self
.assertIn("Argument --name is required.", err
)
419 def test_create__audit(self
):
420 """Test create authentication policy with --audit flag."""
421 name
= self
.unique_name()
423 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
424 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
427 self
.assertIsNone(result
, msg
=err
)
429 # fetch and check policy
430 policy
= self
.get_authentication_policy(name
)
431 self
.assertEqual(str(policy
["msDS-AuthNPolicyEnforced"]), "FALSE")
433 def test_create__enforce(self
):
434 """Test create authentication policy with --enforce flag."""
435 name
= self
.unique_name()
437 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
438 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
441 self
.assertIsNone(result
, msg
=err
)
443 # fetch and check policy
444 policy
= self
.get_authentication_policy(name
)
445 self
.assertEqual(str(policy
["msDS-AuthNPolicyEnforced"]), "TRUE")
447 def test_create__audit_enforce_together(self
):
448 """Test create auth policy using both --audit and --enforce."""
449 name
= self
.unique_name()
451 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
453 "--audit", "--enforce")
455 self
.assertEqual(result
, -1)
456 self
.assertIn("--audit and --enforce cannot be used together.", err
)
458 def test_create__protect_unprotect_together(self
):
459 """Test create authentication policy using --protect and --unprotect."""
460 name
= self
.unique_name()
462 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
464 "--protect", "--unprotect")
466 self
.assertEqual(result
, -1)
467 self
.assertIn("--protect and --unprotect cannot be used together.", err
)
469 def test_user_allowed_to_authenticate_from__set_repeated(self
):
470 """Test repeating similar arguments doesn't make sense to use together.
472 user-allowed-to-authenticate-from set --device-group
473 user-allowed-to-authenticate-from set --device-silo
475 name
= self
.unique_name()
477 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
478 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
480 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
481 "user-allowed-to-authenticate-from",
482 "set", "--name", name
,
484 self
.device_group
.name
,
488 self
.assertEqual(result
, -1)
489 self
.assertIn("Cannot have both --device-group and --device-silo options.", err
)
491 def test_user_allowed_to_authenticate_to__set_repeated(self
):
492 """Test repeating similar arguments doesn't make sense to use together.
494 user-allowed-to-authenticate-to set --by-group
495 user-allowed-to-authenticate-to set --by-silo
497 name
= self
.unique_name()
499 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
500 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
502 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
503 "user-allowed-to-authenticate-to",
504 "set", "--name", name
,
506 self
.device_group
.name
,
510 self
.assertEqual(result
, -1)
511 self
.assertIn("Cannot have both --by-group and --by-silo options.", err
)
513 def test_service_allowed_to_authenticate_from__set_repeated(self
):
514 """Test repeating similar arguments doesn't make sense to use together.
516 service-allowed-to-authenticate-from set --device-group
517 service-allowed-to-authenticate-from set --device-silo
519 name
= self
.unique_name()
521 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
522 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
524 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
525 "service-allowed-to-authenticate-from",
526 "set", "--name", name
,
528 self
.device_group
.name
,
532 self
.assertEqual(result
, -1)
533 self
.assertIn("Cannot have both --device-group and --device-silo options.", err
)
535 def test_service_allowed_to_authenticate_to__set_repeated(self
):
536 """Test repeating similar arguments doesn't make sense to use together.
538 service-allowed-to-authenticate-to set --by-group
539 service-allowed-to-authenticate-to set --by-silo
541 name
= self
.unique_name()
543 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
544 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
546 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
547 "service-allowed-to-authenticate-to",
548 "set", "--name", name
,
550 self
.device_group
.name
,
554 self
.assertEqual(result
, -1)
555 self
.assertIn("Cannot have both --by-group and --by-silo options.", err
)
557 def test_computer_allowed_to_authenticate_to__set_repeated(self
):
558 """Test repeating similar arguments doesn't make sense to use together.
560 computer-allowed-to-authenticate-to set --by-group
561 computer-allowed-to-authenticate-to set --by-silo
563 name
= self
.unique_name()
565 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
566 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
568 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
569 "computer-allowed-to-authenticate-to",
570 "set", "--name", name
,
572 self
.device_group
.name
,
576 self
.assertEqual(result
, -1)
577 self
.assertIn("Cannot have both --by-group and --by-silo options.", err
)
579 def test_create__fails(self
):
580 """Test creating an authentication policy, but it fails."""
581 name
= self
.unique_name()
583 # Raise ModelError when ldb.add() is called.
584 with patch
.object(SamDB
, "add") as add_mock
:
585 add_mock
.side_effect
= ModelError("Custom error message")
586 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
588 self
.assertEqual(result
, -1)
589 self
.assertIn("Custom error message", err
)
591 def test_modify__description(self
):
592 """Test modifying an authentication policy description."""
593 name
= self
.unique_name()
595 # Create a policy to modify for this test.
596 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
597 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
599 # Change the policy description.
600 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
602 "--description", "NewDescription")
603 self
.assertIsNone(result
, msg
=err
)
605 # Verify fields were changed.
606 policy
= self
.get_authentication_policy(name
)
607 self
.assertEqual(str(policy
["description"]), "NewDescription")
609 def test_modify__strong_ntlm_policy(self
):
610 """Test modify strong ntlm policy on the authentication policy."""
611 name
= self
.unique_name()
613 # Create a policy to modify for this test.
614 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
615 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
617 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
619 "--strong-ntlm-policy", "Required")
620 self
.assertIsNone(result
, msg
=err
)
622 # Verify fields were changed.
623 policy
= self
.get_authentication_policy(name
)
624 self
.assertEqual(str(policy
["msDS-StrongNTLMPolicy"]), "2")
626 # Check an invalid choice.
627 with self
.assertRaises((OptionValueError
, SystemExit)):
628 self
.runcmd("domain", "auth", "policy", "modify",
630 "--strong-ntlm-policy", "Invalid")
632 # It is difficult to test the error message text for invalid
633 # choices because inside optparse it will raise OptionValueError
634 # followed by raising SystemExit(2).
636 def test_modify__user_tgt_lifetime_mins(self
):
637 """Test modifying an authentication policy --user-tgt-lifetime-mins.
639 This includes checking the upper and lower bounds.
641 name
= self
.unique_name()
643 # Create a policy to modify for this test.
644 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
645 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
647 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
649 "--user-tgt-lifetime-mins", "120")
650 self
.assertIsNone(result
, msg
=err
)
652 # Verify field was changed.
653 policy
= self
.get_authentication_policy(name
)
654 self
.assertEqual(str(policy
["msDS-UserTGTLifetime"]), str(mins_to_tgt_lifetime(120)))
656 # check lower bounds (45)
657 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
658 "--name", name
+ "Lower",
659 "--user-tgt-lifetime-mins", "44")
660 self
.assertEqual(result
, -1)
661 self
.assertIn("--user-tgt-lifetime-mins must be between 45 and 2147483647",
664 # check upper bounds (2147483647)
665 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
666 "--name", name
+ "Upper",
667 "--user-tgt-lifetime-mins", "2147483648")
668 self
.assertEqual(result
, -1)
669 self
.assertIn("--user-tgt-lifetime-mins must be between 45 and 2147483647",
672 def test_modify__service_tgt_lifetime_mins(self
):
673 """Test modifying an authentication policy --service-tgt-lifetime-mins.
675 This includes checking the upper and lower bounds.
677 name
= self
.unique_name()
679 # Create a policy to modify for this test.
680 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
681 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
683 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
685 "--service-tgt-lifetime-mins", "120")
686 self
.assertIsNone(result
, msg
=err
)
688 # Verify field was changed.
689 policy
= self
.get_authentication_policy(name
)
690 self
.assertEqual(str(policy
["msDS-ServiceTGTLifetime"]), str(mins_to_tgt_lifetime(120)))
692 # check lower bounds (45)
693 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
694 "--name", name
+ "Lower",
695 "--service-tgt-lifetime-mins", "44")
696 self
.assertEqual(result
, -1)
697 self
.assertIn("--service-tgt-lifetime-mins must be between 45 and 2147483647",
700 # check upper bounds (2147483647)
701 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
702 "--name", name
+ "Upper",
703 "--service-tgt-lifetime-mins", "2147483648")
704 self
.assertEqual(result
, -1)
705 self
.assertIn("--service-tgt-lifetime-mins must be between 45 and 2147483647",
708 def test_modify__computer_tgt_lifetime_mins(self
):
709 """Test modifying an authentication policy --computer-tgt-lifetime-mins.
711 This includes checking the upper and lower bounds.
713 name
= self
.unique_name()
715 # Create a policy to modify for this test.
716 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
717 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
719 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
721 "--computer-tgt-lifetime-mins", "120")
722 self
.assertIsNone(result
, msg
=err
)
724 # Verify field was changed.
725 policy
= self
.get_authentication_policy(name
)
726 self
.assertEqual(str(policy
["msDS-ComputerTGTLifetime"]), str(mins_to_tgt_lifetime(120)))
728 # check lower bounds (45)
729 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
730 "--name", name
+ "Lower",
731 "--computer-tgt-lifetime-mins", "44")
732 self
.assertEqual(result
, -1)
733 self
.assertIn("--computer-tgt-lifetime-mins must be between 45 and 2147483647",
736 # check upper bounds (2147483647)
737 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
738 "--name", name
+ "Upper",
739 "--computer-tgt-lifetime-mins", "2147483648")
740 self
.assertEqual(result
, -1)
741 self
.assertIn("--computer-tgt-lifetime-mins must be between 45 and 2147483647",
744 def test_modify__user_allowed_to_authenticate_from(self
):
745 """Modify authentication policy user allowed to authenticate from."""
746 name
= self
.unique_name()
747 expected
= "O:SYG:SYD:(XA;OICI;CR;;;WD;(Member_of {SID(AO)}))"
749 # Create a policy to modify for this test.
750 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
751 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
753 # Modify user allowed to authenticate from field
754 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
756 "--user-allowed-to-authenticate-from",
758 self
.assertIsNone(result
, msg
=err
)
760 # Check user allowed to authenticate from field was modified.
761 policy
= self
.get_authentication_policy(name
)
762 self
.assertEqual(str(policy
["cn"]), name
)
763 desc
= policy
["msDS-UserAllowedToAuthenticateFrom"][0]
764 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
765 self
.assertEqual(sddl
, expected
)
767 def test_user_allowed_to_authenticate_from__set_device_group(self
):
768 """Tests the user-allowed-to-authenticate-from set --device-group shortcut."""
769 name
= self
.unique_name()
770 expected
= "O:SYG:SYD:(XA;OICI;CR;;;WD;(Member_of_any {SID(%s)}))" % (
771 self
.device_group
.object_sid
)
773 # Create a policy to modify for this test.
774 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
775 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
777 # Modify user allowed to authenticate from silo field
778 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
779 "user-allowed-to-authenticate-from",
780 "set", "--name", name
,
781 "--device-group", self
.device_group
.name
)
782 self
.assertIsNone(result
, msg
=err
)
784 # Check generated SDDL.
785 policy
= self
.get_authentication_policy(name
)
786 desc
= policy
["msDS-UserAllowedToAuthenticateFrom"][0]
787 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
788 self
.assertEqual(sddl
, expected
)
790 def test_user_allowed_to_authenticate_from__set_device_silo(self
):
791 """Tests the user-allowed-to-authenticate-from set --device-silo shortcut."""
792 name
= self
.unique_name()
794 # Create a policy to modify for this test.
795 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
796 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
798 # Modify user allowed to authenticate from silo field
799 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
800 "user-allowed-to-authenticate-from",
801 "set", "--name", name
,
802 "--device-silo", "QA")
803 self
.assertIsNone(result
, msg
=err
)
805 # Check generated SDDL.
806 policy
= self
.get_authentication_policy(name
)
807 desc
= policy
["msDS-UserAllowedToAuthenticateFrom"][0]
808 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
811 'O:SYG:SYD:(XA;OICI;CR;;;WD;(@USER.ad://ext/AuthenticationSilo == "QA"))')
813 def test_modify__user_allowed_to_authenticate_to(self
):
814 """Modify authentication policy user allowed to authenticate to."""
815 name
= self
.unique_name()
816 expected
= "O:SYG:SYD:(XA;OICI;CR;;;WD;(Member_of {SID(AO)}))"
818 # Create a policy to modify for this test.
819 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
820 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
822 # Modify user allowed to authenticate to field
823 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
825 "--user-allowed-to-authenticate-to",
827 self
.assertIsNone(result
, msg
=err
)
829 # Check user allowed to authenticate to field was modified.
830 policy
= self
.get_authentication_policy(name
)
831 self
.assertEqual(str(policy
["cn"]), name
)
832 desc
= policy
["msDS-UserAllowedToAuthenticateTo"][0]
833 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
834 self
.assertEqual(sddl
, expected
)
836 def test_user_allowed_to_authenticate_to__set_by_group(self
):
837 """Tests the user-allowed-to-authenticate-to set --by-group shortcut."""
838 name
= self
.unique_name()
839 expected
= "O:SYG:SYD:(XA;OICI;CR;;;WD;(Member_of_any {SID(%s)}))" % (
840 self
.device_group
.object_sid
)
842 # Create a policy to modify for this test.
843 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
844 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
846 # Modify user allowed to authenticate to field
847 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
848 "user-allowed-to-authenticate-to",
849 "set", "--name", name
,
850 "--by-group", self
.device_group
.name
)
851 self
.assertIsNone(result
, msg
=err
)
853 # Check user allowed to authenticate to field was modified.
854 policy
= self
.get_authentication_policy(name
)
855 self
.assertEqual(str(policy
["cn"]), name
)
856 desc
= policy
["msDS-UserAllowedToAuthenticateTo"][0]
857 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
858 self
.assertEqual(sddl
, expected
)
860 def test_user_allowed_to_authenticate_to__set_by_silo(self
):
861 """Tests the user-allowed-to-authenticate-to set --by-silo shortcut."""
862 name
= self
.unique_name()
863 expected
= ('O:SYG:SYD:(XA;OICI;CR;;;WD;(@USER.ad://ext/'
864 'AuthenticationSilo == "Developers"))')
866 # Create a policy to modify for this test.
867 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
868 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
870 # Modify user allowed to authenticate to field
871 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
872 "user-allowed-to-authenticate-to",
873 "set", "--name", name
,
874 "--by-silo", "Developers")
875 self
.assertIsNone(result
, msg
=err
)
877 # Check user allowed to authenticate to field was modified.
878 policy
= self
.get_authentication_policy(name
)
879 self
.assertEqual(str(policy
["cn"]), name
)
880 desc
= policy
["msDS-UserAllowedToAuthenticateTo"][0]
881 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
882 self
.assertEqual(sddl
, expected
)
884 def test_modify__service_allowed_to_authenticate_from(self
):
885 """Modify authentication policy service allowed to authenticate from."""
886 name
= self
.unique_name()
887 expected
= "O:SYG:SYD:(XA;OICI;CR;;;WD;(Member_of {SID(AO)}))"
889 # Create a policy to modify for this test.
890 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
891 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
893 # Modify service allowed to authenticate from field
894 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
896 "--service-allowed-to-authenticate-from",
898 self
.assertIsNone(result
, msg
=err
)
900 # Check service allowed to authenticate from field was modified.
901 policy
= self
.get_authentication_policy(name
)
902 self
.assertEqual(str(policy
["cn"]), name
)
903 desc
= policy
["msDS-ServiceAllowedToAuthenticateFrom"][0]
904 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
905 self
.assertEqual(sddl
, expected
)
907 def test_service_allowed_to_authenticate_from__set_device_group(self
):
908 """Tests the service-allowed-to-authenticate-from set --device-group shortcut."""
909 name
= self
.unique_name()
910 expected
= "O:SYG:SYD:(XA;OICI;CR;;;WD;(Member_of_any {SID(%s)}))" % (
911 self
.device_group
.object_sid
)
913 # Create a policy to modify for this test.
914 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
915 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
917 # Modify user allowed to authenticate from silo field
918 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
919 "service-allowed-to-authenticate-from",
920 "set", "--name", name
,
921 "--device-group", self
.device_group
.name
)
922 self
.assertIsNone(result
, msg
=err
)
924 # Check generated SDDL.
925 policy
= self
.get_authentication_policy(name
)
926 desc
= policy
["msDS-ServiceAllowedToAuthenticateFrom"][0]
927 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
928 self
.assertEqual(sddl
, expected
)
930 def test_service_allowed_to_authenticate_from__set_device_silo(self
):
931 """Tests the service-allowed-to-authenticate-from set --device-silo shortcut."""
932 name
= self
.unique_name()
934 # Create a policy to modify for this test.
935 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
936 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
938 # Modify user allowed to authenticate from silo field
939 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
940 "service-allowed-to-authenticate-from",
941 "set", "--name", name
,
942 "--device-silo", "Developers")
943 self
.assertIsNone(result
, msg
=err
)
945 # Check generated SDDL.
946 policy
= self
.get_authentication_policy(name
)
947 desc
= policy
["msDS-ServiceAllowedToAuthenticateFrom"][0]
948 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
951 'O:SYG:SYD:(XA;OICI;CR;;;WD;(@USER.ad://ext/AuthenticationSilo == "Developers"))')
953 def test_modify__service_allowed_to_authenticate_to(self
):
954 """Modify authentication policy service allowed to authenticate to."""
955 name
= self
.unique_name()
956 expected
= "O:SYG:SYD:(XA;OICI;CR;;;WD;(Member_of {SID(AO)}))"
958 # Create a policy to modify for this test.
959 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
960 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
962 # Modify service allowed to authenticate to field
963 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
965 "--service-allowed-to-authenticate-to",
967 self
.assertIsNone(result
, msg
=err
)
969 # Check service allowed to authenticate to field was modified.
970 policy
= self
.get_authentication_policy(name
)
971 self
.assertEqual(str(policy
["cn"]), name
)
972 desc
= policy
["msDS-ServiceAllowedToAuthenticateTo"][0]
973 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
974 self
.assertEqual(sddl
, expected
)
976 def test_service_allowed_to_authenticate_to__set_by_group(self
):
977 """Tests the service-allowed-to-authenticate-to set --by-group shortcut."""
978 name
= self
.unique_name()
979 expected
= "O:SYG:SYD:(XA;OICI;CR;;;WD;(Member_of_any {SID(%s)}))" % (
980 self
.device_group
.object_sid
)
982 # Create a policy to modify for this test.
983 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
984 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
986 # Modify user allowed to authenticate to field
987 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
988 "service-allowed-to-authenticate-to",
989 "set", "--name", name
,
990 "--by-group", self
.device_group
.name
)
991 self
.assertIsNone(result
, msg
=err
)
993 # Check user allowed to authenticate to field was modified.
994 policy
= self
.get_authentication_policy(name
)
995 self
.assertEqual(str(policy
["cn"]), name
)
996 desc
= policy
["msDS-ServiceAllowedToAuthenticateTo"][0]
997 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
998 self
.assertEqual(sddl
, expected
)
1000 def test_service_allowed_to_authenticate_to__set_by_silo(self
):
1001 """Tests the service-allowed-to-authenticate-to set --by-silo shortcut."""
1002 name
= self
.unique_name()
1003 expected
= ('O:SYG:SYD:(XA;OICI;CR;;;WD;(@USER.ad://ext/'
1004 'AuthenticationSilo == "QA"))')
1006 # Create a policy to modify for this test.
1007 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
1008 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
1010 # Modify user allowed to authenticate to field
1011 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
1012 "service-allowed-to-authenticate-to",
1013 "set", "--name", name
,
1015 self
.assertIsNone(result
, msg
=err
)
1017 # Check user allowed to authenticate to field was modified.
1018 policy
= self
.get_authentication_policy(name
)
1019 self
.assertEqual(str(policy
["cn"]), name
)
1020 desc
= policy
["msDS-ServiceAllowedToAuthenticateTo"][0]
1021 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
1022 self
.assertEqual(sddl
, expected
)
1024 def test_modify__computer_allowed_to_authenticate_to(self
):
1025 """Modify authentication policy computer allowed to authenticate to."""
1026 name
= self
.unique_name()
1027 expected
= "O:SYG:SYD:(XA;OICI;CR;;;WD;(Member_of {SID(AO)}))"
1029 # Create a policy to modify for this test.
1030 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
1031 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
1033 # Modify computer allowed to authenticate to field
1034 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
1036 "--computer-allowed-to-authenticate-to",
1038 self
.assertIsNone(result
, msg
=err
)
1040 # Check computer allowed to authenticate to field was modified.
1041 policy
= self
.get_authentication_policy(name
)
1042 self
.assertEqual(str(policy
["cn"]), name
)
1043 desc
= policy
["msDS-ComputerAllowedToAuthenticateTo"][0]
1044 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
1045 self
.assertEqual(sddl
, expected
)
1047 def test_computer_allowed_to_authenticate_to__set_by_group(self
):
1048 """Tests the computer-allowed-to-authenticate-to set --by-group shortcut."""
1049 name
= self
.unique_name()
1050 expected
= "O:SYG:SYD:(XA;OICI;CR;;;WD;(Member_of_any {SID(%s)}))" % (
1051 self
.device_group
.object_sid
)
1053 # Create a policy to modify for this test.
1054 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
1055 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
1057 # Modify user allowed to authenticate to field
1058 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
1059 "computer-allowed-to-authenticate-to",
1060 "set", "--name", name
, "--by-group",
1061 self
.device_group
.name
)
1062 self
.assertIsNone(result
, msg
=err
)
1064 # Check user allowed to authenticate to field was modified.
1065 policy
= self
.get_authentication_policy(name
)
1066 self
.assertEqual(str(policy
["cn"]), name
)
1067 desc
= policy
["msDS-ComputerAllowedToAuthenticateTo"][0]
1068 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
1069 self
.assertEqual(sddl
, expected
)
1071 def test_computer_allowed_to_authenticate_to__set_by_silo(self
):
1072 """Tests the computer-allowed-to-authenticate-to set --by-silo shortcut."""
1073 name
= self
.unique_name()
1074 expected
= ('O:SYG:SYD:(XA;OICI;CR;;;WD;(@USER.ad://ext/'
1075 'AuthenticationSilo == "QA"))')
1077 # Create a policy to modify for this test.
1078 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
1079 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
1081 # Modify user allowed to authenticate to field
1082 result
, out
, err
= self
.runcmd("domain", "auth", "policy",
1083 "computer-allowed-to-authenticate-to",
1084 "set", "--name", name
, "--by-silo",
1086 self
.assertIsNone(result
, msg
=err
)
1088 # Check user allowed to authenticate to field was modified.
1089 policy
= self
.get_authentication_policy(name
)
1090 self
.assertEqual(str(policy
["cn"]), name
)
1091 desc
= policy
["msDS-ComputerAllowedToAuthenticateTo"][0]
1092 sddl
= ndr_unpack(security
.descriptor
, desc
).as_sddl()
1093 self
.assertEqual(sddl
, expected
)
1095 def test_modify__name_missing(self
):
1096 """Test modify authentication but the --name argument is missing."""
1097 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
1098 "--description", "NewDescription")
1099 self
.assertEqual(result
, -1)
1100 self
.assertIn("Argument --name is required.", err
)
1102 def test_modify__notfound(self
):
1103 """Test modify an authentication silo that doesn't exist."""
1104 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
1105 "--name", "doesNotExist",
1106 "--description", "NewDescription")
1107 self
.assertEqual(result
, -1)
1108 self
.assertIn("Authentication policy doesNotExist not found.", err
)
1110 def test_modify__audit_enforce(self
):
1111 """Test modify authentication policy using --audit and --enforce."""
1112 name
= self
.unique_name()
1114 # Create a policy to modify for this test.
1115 self
.addCleanup(self
.delete_authentication_policy
,
1116 name
=name
, force
=True)
1117 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
1119 # Change to audit, the default is --enforce.
1120 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
1123 self
.assertIsNone(result
, msg
=err
)
1125 # Check that the policy was changed to --audit.
1126 policy
= self
.get_authentication_policy(name
)
1127 self
.assertEqual(str(policy
["msDS-AuthNPolicyEnforced"]), "FALSE")
1129 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
1132 self
.assertIsNone(result
, msg
=err
)
1134 # Check if the policy was changed back to --enforce.
1135 policy
= self
.get_authentication_policy(name
)
1136 self
.assertEqual(str(policy
["msDS-AuthNPolicyEnforced"]), "TRUE")
1138 def test_modify__protect_unprotect(self
):
1139 """Test modify authentication policy using --protect and --unprotect."""
1140 name
= self
.unique_name()
1142 # Create a policy to modify for this test.
1143 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
1144 self
.runcmd("domain", "auth", "policy", "create", "--name", name
)
1146 utils
= SDUtils(self
.samdb
)
1147 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
1150 self
.assertIsNone(result
, msg
=err
)
1152 # Check that claim type was protected.
1153 policy
= self
.get_authentication_policy(name
)
1154 desc
= utils
.get_sd_as_sddl(policy
["dn"])
1155 self
.assertIn("(D;;DTSD;;;WD)", desc
)
1157 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
1160 self
.assertIsNone(result
, msg
=err
)
1162 # Check that claim type was unprotected.
1163 policy
= self
.get_authentication_policy(name
)
1164 desc
= utils
.get_sd_as_sddl(policy
["dn"])
1165 self
.assertNotIn("(D;;DTSD;;;WD)", desc
)
1167 def test_modify__audit_enforce_together(self
):
1168 """Test modify auth policy using both --audit and --enforce."""
1169 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
1170 "--name", "User Policy",
1171 "--audit", "--enforce")
1172 self
.assertEqual(result
, -1)
1173 self
.assertIn("--audit and --enforce cannot be used together.", err
)
1175 def test_modify__protect_unprotect_together(self
):
1176 """Test modify authentication policy using --protect and --unprotect."""
1177 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
1178 "--name", "User Policy",
1179 "--protect", "--unprotect")
1180 self
.assertEqual(result
, -1)
1181 self
.assertIn("--protect and --unprotect cannot be used together.", err
)
1183 def test_modify__fails(self
):
1184 """Test modifying an authentication policy, but it fails."""
1185 # Raise ModelError when ldb.add() is called.
1186 with patch
.object(SamDB
, "modify") as modify_mock
:
1187 modify_mock
.side_effect
= ModelError("Custom error message")
1188 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "modify",
1189 "--name", "User Policy",
1190 "--description", "New description")
1191 self
.assertEqual(result
, -1)
1192 self
.assertIn("Custom error message", err
)
1194 def test_delete__success(self
):
1195 """Test deleting an authentication policy that is not protected."""
1196 # Create non-protected authentication policy.
1197 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
1198 "--name=deleteTest")
1199 self
.assertIsNone(result
, msg
=err
)
1200 policy
= self
.get_authentication_policy("deleteTest")
1201 self
.assertIsNotNone(policy
)
1204 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "delete",
1205 "--name", "deleteTest")
1206 self
.assertIsNone(result
, msg
=err
)
1208 # Authentication policy shouldn't exist anymore.
1209 policy
= self
.get_authentication_policy("deleteTest")
1210 self
.assertIsNone(policy
)
1212 def test_delete__protected(self
):
1213 """Test deleting a protected auth policy, with and without --force."""
1214 # Create protected authentication policy.
1215 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
1216 "--name=deleteProtected",
1218 self
.assertIsNone(result
, msg
=err
)
1219 policy
= self
.get_authentication_policy("deleteProtected")
1220 self
.assertIsNotNone(policy
)
1223 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "delete",
1224 "--name=deleteProtected")
1225 self
.assertEqual(result
, -1)
1227 # Authentication silo should still exist.
1228 policy
= self
.get_authentication_policy("deleteProtected")
1229 self
.assertIsNotNone(policy
)
1231 # Try a force delete instead.
1232 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "delete",
1233 "--name=deleteProtected", "--force")
1234 self
.assertIsNone(result
, msg
=err
)
1236 # Authentication silo shouldn't exist anymore.
1237 policy
= self
.get_authentication_policy("deleteProtected")
1238 self
.assertIsNone(policy
)
1240 def test_delete__notfound(self
):
1241 """Test deleting an authentication policy that doesn't exist."""
1242 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "delete",
1243 "--name", "doesNotExist")
1244 self
.assertEqual(result
, -1)
1245 self
.assertIn("Authentication policy doesNotExist not found.", err
)
1247 def test_delete__name_required(self
):
1248 """Test deleting an authentication policy without --name argument."""
1249 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "delete")
1250 self
.assertEqual(result
, -1)
1251 self
.assertIn("Argument --name is required.", err
)
1253 def test_delete__force_fails(self
):
1254 """Test deleting an authentication policy with --force, but it fails."""
1255 name
= self
.unique_name()
1257 # Create protected authentication policy.
1258 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
1259 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
1262 self
.assertIsNone(result
, msg
=err
)
1265 policy
= self
.get_authentication_policy(name
)
1266 self
.assertIsNotNone(policy
)
1268 # Try doing delete with --force.
1269 # Patch SDUtils.dacl_delete_aces with a Mock that raises ModelError.
1270 with patch
.object(SDUtils
, "dacl_delete_aces") as delete_mock
:
1271 delete_mock
.side_effect
= ModelError("Custom error message")
1272 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "delete",
1275 self
.assertEqual(result
, -1)
1276 self
.assertIn("Custom error message", err
)
1278 def test_delete__fails(self
):
1279 """Test deleting an authentication policy, but it fails."""
1280 name
= self
.unique_name()
1282 # Create regular authentication policy.
1283 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
1284 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
1286 self
.assertIsNone(result
, msg
=err
)
1289 policy
= self
.get_authentication_policy(name
)
1290 self
.assertIsNotNone(policy
)
1292 # Raise ModelError when ldb.delete() is called.
1293 with patch
.object(SamDB
, "delete") as delete_mock
:
1294 delete_mock
.side_effect
= ModelError("Custom error message")
1295 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "delete",
1297 self
.assertEqual(result
, -1)
1298 self
.assertIn("Custom error message", err
)
1300 # When not using --force we get a hint.
1301 self
.assertIn("Try --force", err
)
1303 def test_delete__protected_fails(self
):
1304 """Test deleting an authentication policy, but it fails."""
1305 name
= self
.unique_name()
1307 # Create protected authentication policy.
1308 self
.addCleanup(self
.delete_authentication_policy
, name
=name
, force
=True)
1309 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "create",
1312 self
.assertIsNone(result
, msg
=err
)
1315 policy
= self
.get_authentication_policy(name
)
1316 self
.assertIsNotNone(policy
)
1318 # Raise ModelError when ldb.delete() is called.
1319 with patch
.object(SamDB
, "delete") as delete_mock
:
1320 delete_mock
.side_effect
= ModelError("Custom error message")
1321 result
, out
, err
= self
.runcmd("domain", "auth", "policy", "delete",
1324 self
.assertEqual(result
, -1)
1325 self
.assertIn("Custom error message", err
)
1327 # When using --force we don't get the hint.
1328 self
.assertNotIn("Try --force", err
)