mirror of
https://github.com/samba-team/samba.git
synced 2025-02-04 17:47:26 +03:00
python: silos: add support for allowed to authenticate from silo shortcut
this avoids the need to write SDDL, the user just needs to give the silo name Signed-off-by: Rob van der Linde <rob@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org> Autobuild-User(master): Andrew Bartlett <abartlet@samba.org> Autobuild-Date(master): Fri Oct 27 00:30:05 UTC 2023 on atb-devel-224
This commit is contained in:
parent
8491693575
commit
0bb67a3a7e
@ -22,13 +22,24 @@
|
||||
|
||||
import samba.getopt as options
|
||||
from samba.netcmd import Command, CommandError, Option, SuperCommand
|
||||
from samba.netcmd.domain.models import AuthenticationPolicy
|
||||
from samba.netcmd.domain.models import AuthenticationPolicy, AuthenticationSilo
|
||||
from samba.netcmd.domain.models.auth_policy import MIN_TGT_LIFETIME,\
|
||||
MAX_TGT_LIFETIME, StrongNTLMPolicy
|
||||
from samba.netcmd.domain.models.exceptions import ModelError
|
||||
from samba.netcmd.validators import Range
|
||||
|
||||
|
||||
def check_similar_args(option, args):
|
||||
"""Helper method for checking similar mutually exclusive args.
|
||||
|
||||
Example: --user-allowed-to-authenticate-from and
|
||||
--user-allowed-to-authenticate-from-silo
|
||||
"""
|
||||
num = sum(arg is not None for arg in args)
|
||||
if num > 1:
|
||||
raise CommandError(f"{option} argument repeated {num} times.")
|
||||
|
||||
|
||||
class UserOptions(options.OptionGroup):
|
||||
"""User options used by policy create and policy modify commands."""
|
||||
|
||||
@ -49,6 +60,10 @@ class UserOptions(options.OptionGroup):
|
||||
help="Conditions user is allowed to authenticate from.",
|
||||
type=str, dest="allowed_to_authenticate_from",
|
||||
action="callback", callback=self.set_option)
|
||||
self.add_option("--user-allowed-to-authenticate-from-silo",
|
||||
help="User is allowed to authenticate from silo.",
|
||||
type=str, dest="allowed_to_authenticate_from_silo",
|
||||
action="callback", callback=self.set_option)
|
||||
self.add_option("--user-allowed-to-authenticate-to",
|
||||
help="Conditions user is allowed to authenticate to.",
|
||||
type=str, dest="allowed_to_authenticate_to",
|
||||
@ -75,6 +90,10 @@ class ServiceOptions(options.OptionGroup):
|
||||
help="Conditions service is allowed to authenticate from.",
|
||||
type=str, dest="allowed_to_authenticate_from",
|
||||
action="callback", callback=self.set_option)
|
||||
self.add_option("--service-allowed-to-authenticate-from-silo",
|
||||
help="Service is allowed to authenticate from silo.",
|
||||
type=str, dest="allowed_to_authenticate_from_silo",
|
||||
action="callback", callback=self.set_option)
|
||||
self.add_option("--service-allowed-to-authenticate-to",
|
||||
help="Conditions service is allowed to authenticate to.",
|
||||
type=str, dest="allowed_to_authenticate_to",
|
||||
@ -217,8 +236,28 @@ class cmd_domain_auth_policy_create(Command):
|
||||
if audit and enforce:
|
||||
raise CommandError("--audit and --enforce cannot be used together.")
|
||||
|
||||
# Check for repeated, similar arguments.
|
||||
check_similar_args("--user-allowed-to-authenticate-from",
|
||||
[useropts.allowed_to_authenticate_from,
|
||||
useropts.allowed_to_authenticate_from_silo])
|
||||
check_similar_args("--service-allowed-to-authenticate-from",
|
||||
[serviceopts.allowed_to_authenticate_from,
|
||||
serviceopts.allowed_to_authenticate_from_silo])
|
||||
|
||||
ldb = self.ldb_connect(hostopts, sambaopts, credopts)
|
||||
|
||||
# Generate SDDL for authenticating users from a silo
|
||||
if useropts.allowed_to_authenticate_from_silo:
|
||||
silo = AuthenticationSilo.get(
|
||||
ldb, cn=useropts.allowed_to_authenticate_from_silo)
|
||||
useropts.allowed_to_authenticate_from = silo.get_authentication_sddl()
|
||||
|
||||
# Generate SDDL for authenticating service accounts from a silo
|
||||
if serviceopts.allowed_to_authenticate_from_silo:
|
||||
silo = AuthenticationSilo.get(
|
||||
ldb, cn=serviceopts.allowed_to_authenticate_from_silo)
|
||||
serviceopts.allowed_to_authenticate_from = silo.get_authentication_sddl()
|
||||
|
||||
try:
|
||||
policy = AuthenticationPolicy.get(ldb, cn=name)
|
||||
except ModelError as e:
|
||||
@ -313,8 +352,28 @@ class cmd_domain_auth_policy_modify(Command):
|
||||
if audit and enforce:
|
||||
raise CommandError("--audit and --enforce cannot be used together.")
|
||||
|
||||
# Check for repeated, similar arguments.
|
||||
check_similar_args("--user-allowed-to-authenticate-from",
|
||||
[useropts.allowed_to_authenticate_from,
|
||||
useropts.allowed_to_authenticate_from_silo])
|
||||
check_similar_args("--service-allowed-to-authenticate-from",
|
||||
[serviceopts.allowed_to_authenticate_from,
|
||||
serviceopts.allowed_to_authenticate_from_silo])
|
||||
|
||||
ldb = self.ldb_connect(hostopts, sambaopts, credopts)
|
||||
|
||||
# Generate SDDL for authenticating users from a silo
|
||||
if useropts.allowed_to_authenticate_from_silo:
|
||||
silo = AuthenticationSilo.get(
|
||||
ldb, cn=useropts.allowed_to_authenticate_from_silo)
|
||||
useropts.allowed_to_authenticate_from = silo.get_authentication_sddl()
|
||||
|
||||
# Generate SDDL for authenticating service accounts from a silo
|
||||
if serviceopts.allowed_to_authenticate_from_silo:
|
||||
silo = AuthenticationSilo.get(
|
||||
ldb, cn=serviceopts.allowed_to_authenticate_from_silo)
|
||||
serviceopts.allowed_to_authenticate_from = silo.get_authentication_sddl()
|
||||
|
||||
try:
|
||||
policy = AuthenticationPolicy.get(ldb, cn=name)
|
||||
except ModelError as e:
|
||||
|
@ -22,6 +22,8 @@
|
||||
|
||||
from ldb import FLAG_MOD_ADD, FLAG_MOD_DELETE, LdbError, Message, MessageElement
|
||||
|
||||
from samba.sd_utils import escaped_claim_id
|
||||
|
||||
from .exceptions import AddMemberError, RemoveMemberError
|
||||
from .fields import DnField, BooleanField, StringField
|
||||
from .model import Model
|
||||
@ -96,3 +98,7 @@ class AuthenticationSilo(Model):
|
||||
|
||||
# If the modify operation was successful refresh members field.
|
||||
self.refresh(ldb, fields=["members"])
|
||||
|
||||
def get_authentication_sddl(self):
|
||||
return ("O:SYG:SYD:(XA;OICI;CR;;;WD;(@USER.ad://ext/"
|
||||
f"AuthenticationSilo/{escaped_claim_id(self.name)}))")
|
||||
|
@ -153,6 +153,28 @@ class AuthPolicyCmdTestCase(BaseAuthCmdTest):
|
||||
self.assertIn("--user-tgt-lifetime-mins must be between 45 and 2147483647",
|
||||
err)
|
||||
|
||||
def test_create__user_allowed_to_authenticate_from_silo(self):
|
||||
"""Tests the --user-allowed-to-authenticate-from-silo shortcut."""
|
||||
name = self.unique_name()
|
||||
|
||||
self.addCleanup(self.delete_authentication_policy, name=name, force=True)
|
||||
result, out, err = self.runcmd("domain", "auth", "policy", "create",
|
||||
"--name", name,
|
||||
"--user-allowed-to-authenticate-from-silo",
|
||||
"Developers")
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
# Check policy fields.
|
||||
policy = self.get_authentication_policy(name)
|
||||
self.assertEqual(str(policy["cn"]), name)
|
||||
|
||||
# Check generated SDDL.
|
||||
desc = policy["msDS-UserAllowedToAuthenticateFrom"][0]
|
||||
sddl = ndr_unpack(security.descriptor, desc).as_sddl()
|
||||
self.assertEqual(
|
||||
sddl,
|
||||
"O:SYG:SYD:(XA;OICI;CR;;;WD;(@USER.ad://ext/AuthenticationSilo/Developers))")
|
||||
|
||||
def test_create__service_tgt_lifetime_mins(self):
|
||||
"""Test create a new authentication policy with --service-tgt-lifetime-mins.
|
||||
|
||||
@ -187,6 +209,28 @@ class AuthPolicyCmdTestCase(BaseAuthCmdTest):
|
||||
self.assertIn("--service-tgt-lifetime-mins must be between 45 and 2147483647",
|
||||
err)
|
||||
|
||||
def test_create__service_allowed_to_authenticate_from_silo(self):
|
||||
"""Tests the --service-allowed-to-authenticate-from-silo shortcut."""
|
||||
name = self.unique_name()
|
||||
|
||||
self.addCleanup(self.delete_authentication_policy, name=name, force=True)
|
||||
result, out, err = self.runcmd("domain", "auth", "policy", "create",
|
||||
"--name", name,
|
||||
"--service-allowed-to-authenticate-from-silo",
|
||||
"Managers")
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
# Check policy fields.
|
||||
policy = self.get_authentication_policy(name)
|
||||
self.assertEqual(str(policy["cn"]), name)
|
||||
desc = policy["msDS-ServiceAllowedToAuthenticateFrom"][0]
|
||||
|
||||
# Check generated SDDL.
|
||||
sddl = ndr_unpack(security.descriptor, desc).as_sddl()
|
||||
self.assertEqual(
|
||||
sddl,
|
||||
"O:SYG:SYD:(XA;OICI;CR;;;WD;(@USER.ad://ext/AuthenticationSilo/Managers))")
|
||||
|
||||
def test_create__computer_tgt_lifetime_mins(self):
|
||||
"""Test create a new authentication policy with --computer-tgt-lifetime-mins.
|
||||
|
||||
@ -316,6 +360,44 @@ class AuthPolicyCmdTestCase(BaseAuthCmdTest):
|
||||
self.assertEqual(result, -1)
|
||||
self.assertIn("--protect and --unprotect cannot be used together.", err)
|
||||
|
||||
def test_create__user_allowed_to_authenticate_from_repeated(self):
|
||||
"""Test repeating similar arguments doesn't make sense to use together.
|
||||
|
||||
--user-allowed-to-authenticate-from
|
||||
--user-allowed-to-authenticate-from-silo
|
||||
"""
|
||||
sddl = "O:SYG:SYD:(XA;OICI;CR;;;WD;(@USER.ad://ext/AuthenticationSilo/Developers))"
|
||||
name = self.unique_name()
|
||||
|
||||
result, out, err = self.runcmd("domain", "auth", "policy", "create",
|
||||
"--name", name,
|
||||
"--user-allowed-to-authenticate-from",
|
||||
sddl,
|
||||
"--user-allowed-to-authenticate-from-silo",
|
||||
"Managers")
|
||||
|
||||
self.assertEqual(result, -1)
|
||||
self.assertIn("--user-allowed-to-authenticate-from argument repeated 2 times.", err)
|
||||
|
||||
def test_create__service_allowed_to_authenticate_from_repeated(self):
|
||||
"""Test repeating similar arguments doesn't make sense to use together.
|
||||
|
||||
--service-allowed-to-authenticate-from
|
||||
--service-allowed-to-authenticate-from-silo
|
||||
"""
|
||||
sddl = "O:SYG:SYD:(XA;OICI;CR;;;WD;(@USER.ad://ext/AuthenticationSilo/Managers))"
|
||||
name = self.unique_name()
|
||||
|
||||
result, out, err = self.runcmd("domain", "auth", "policy", "create",
|
||||
"--name", name,
|
||||
"--service-allowed-to-authenticate-from",
|
||||
sddl,
|
||||
"--service-allowed-to-authenticate-from-silo",
|
||||
"QA")
|
||||
|
||||
self.assertEqual(result, -1)
|
||||
self.assertIn("--service-allowed-to-authenticate-from argument repeated 2 times.", err)
|
||||
|
||||
def test_create__fails(self):
|
||||
"""Test creating an authentication policy, but it fails."""
|
||||
name = self.unique_name()
|
||||
@ -504,6 +586,29 @@ class AuthPolicyCmdTestCase(BaseAuthCmdTest):
|
||||
sddl = ndr_unpack(security.descriptor, desc).as_sddl()
|
||||
self.assertEqual(sddl, expected)
|
||||
|
||||
def test_modify__user_allowed_to_authenticate_from_silo(self):
|
||||
"""Test the --user-allowed-to-authenticate-from-silo shortcut."""
|
||||
name = self.unique_name()
|
||||
|
||||
# Create a policy to modify for this test.
|
||||
self.addCleanup(self.delete_authentication_policy, name=name, force=True)
|
||||
self.runcmd("domain", "auth", "policy", "create", "--name", name)
|
||||
|
||||
# Modify user allowed to authenticate from silo field
|
||||
result, out, err = self.runcmd("domain", "auth", "policy", "modify",
|
||||
"--name", name,
|
||||
"--user-allowed-to-authenticate-from-silo",
|
||||
"QA")
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
# Check generated SDDL.
|
||||
policy = self.get_authentication_policy(name)
|
||||
desc = policy["msDS-UserAllowedToAuthenticateFrom"][0]
|
||||
sddl = ndr_unpack(security.descriptor, desc).as_sddl()
|
||||
self.assertEqual(
|
||||
sddl,
|
||||
"O:SYG:SYD:(XA;OICI;CR;;;WD;(@USER.ad://ext/AuthenticationSilo/QA))")
|
||||
|
||||
def test_modify__user_allowed_to_authenticate_to(self):
|
||||
"""Modify authentication policy user allowed to authenticate to."""
|
||||
name = self.unique_name()
|
||||
@ -550,6 +655,29 @@ class AuthPolicyCmdTestCase(BaseAuthCmdTest):
|
||||
sddl = ndr_unpack(security.descriptor, desc).as_sddl()
|
||||
self.assertEqual(sddl, expected)
|
||||
|
||||
def test_modify__service_allowed_to_authenticate_from_silo(self):
|
||||
"""Test the --service-allowed-to-authenticate-from-silo shortcut."""
|
||||
name = self.unique_name()
|
||||
|
||||
# Create a policy to modify for this test.
|
||||
self.addCleanup(self.delete_authentication_policy, name=name, force=True)
|
||||
self.runcmd("domain", "auth", "policy", "create", "--name", name)
|
||||
|
||||
# Modify user allowed to authenticate from silo field
|
||||
result, out, err = self.runcmd("domain", "auth", "policy", "modify",
|
||||
"--name", name,
|
||||
"--service-allowed-to-authenticate-from-silo",
|
||||
"Developers")
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
# Check generated SDDL.
|
||||
policy = self.get_authentication_policy(name)
|
||||
desc = policy["msDS-ServiceAllowedToAuthenticateFrom"][0]
|
||||
sddl = ndr_unpack(security.descriptor, desc).as_sddl()
|
||||
self.assertEqual(
|
||||
sddl,
|
||||
"O:SYG:SYD:(XA;OICI;CR;;;WD;(@USER.ad://ext/AuthenticationSilo/Developers))")
|
||||
|
||||
def test_modify__service_allowed_to_authenticate_to(self):
|
||||
"""Modify authentication policy service allowed to authenticate to."""
|
||||
name = self.unique_name()
|
||||
|
Loading…
x
Reference in New Issue
Block a user