mirror of
https://github.com/samba-team/samba.git
synced 2025-01-22 22:04:08 +03:00
netcmd: tests: add tests for service-account commands
Signed-off-by: Rob van der Linde <rob@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
This commit is contained in:
parent
a7a35ae5e3
commit
85ca9e7cba
333
python/samba/tests/samba_tool/service_account.py
Normal file
333
python/samba/tests/samba_tool/service_account.py
Normal file
@ -0,0 +1,333 @@
|
||||
# Unix SMB/CIFS implementation.
|
||||
#
|
||||
# Tests for samba-tool service-account commands.
|
||||
#
|
||||
# Copyright (C) Catalyst.Net Ltd. 2024
|
||||
#
|
||||
# Written by Rob van der Linde <rob@catalyst.net.nz>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
from samba.netcmd.domain.models import Group, GroupManagedServiceAccount, User
|
||||
from samba.netcmd.domain.models.constants import GROUP_MSA_MEMBERSHIP_DEFAULT
|
||||
|
||||
from .base import SambaToolCmdTest
|
||||
|
||||
HOST = "ldap://{DC_SERVER}".format(**os.environ)
|
||||
CREDS = "-U{DC_USERNAME}%{DC_PASSWORD}".format(**os.environ)
|
||||
|
||||
|
||||
class ServiceAccountTests(SambaToolCmdTest):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.samdb = cls.getSamDB("-H", HOST, CREDS)
|
||||
super().setUpClass()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Setup initial data without the samba-tool command."""
|
||||
cls.accounts = [
|
||||
GroupManagedServiceAccount.create(cls.samdb, name="foo",
|
||||
dns_host_name="example.com"),
|
||||
GroupManagedServiceAccount.create(cls.samdb, name="bar",
|
||||
dns_host_name="example.com"),
|
||||
GroupManagedServiceAccount.create(cls.samdb, name="baz",
|
||||
dns_host_name="example.com"),
|
||||
]
|
||||
|
||||
for account in cls.accounts:
|
||||
cls.addClassCleanup(account.delete, cls.samdb)
|
||||
|
||||
@classmethod
|
||||
def _run(cls, *argv):
|
||||
"""Override _run, so we don't always have to pass HOST and CREDS."""
|
||||
args = list(argv)
|
||||
args.extend(["-H", HOST, CREDS])
|
||||
return super()._run(*args)
|
||||
|
||||
runcmd = _run
|
||||
runsubcmd = _run
|
||||
|
||||
@classmethod
|
||||
def delete_service_account(cls, name):
|
||||
"""Delete a service account using samba-tool."""
|
||||
result, out, err = cls.runcmd("service-account", "delete",
|
||||
"--name", name)
|
||||
assert result is None
|
||||
assert out.startswith("Deleted group managed service account")
|
||||
|
||||
@classmethod
|
||||
def create_service_account(cls, name, dns_host_name="example.com",
|
||||
managed_password_interval=None):
|
||||
"""Create a service account using samba-tool.
|
||||
|
||||
Adds a class cleanup to automatically delete the gmsa and the end
|
||||
of the test case.
|
||||
"""
|
||||
# required arguments
|
||||
cmd = ["service-account", "create",
|
||||
"--name", name,
|
||||
"--dns-host-name", dns_host_name]
|
||||
|
||||
# defaults to 30 if left None
|
||||
if managed_password_interval is not None:
|
||||
cmd += ["--managed-password-interval", str(managed_password_interval)]
|
||||
|
||||
# create gmsa and setup cleanup
|
||||
result, out, err = cls.runcmd(*cmd)
|
||||
assert result is None
|
||||
assert out.startswith("Created group managed service account")
|
||||
cls.addClassCleanup(cls.delete_service_account, name=name)
|
||||
|
||||
def test_list(self):
|
||||
"""List group managed service accounts with samba-tool."""
|
||||
result, out, err = self.runcmd("service-account", "list")
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
self.assertIn("foo$", out)
|
||||
self.assertIn("bar$", out)
|
||||
self.assertIn("baz$", out)
|
||||
|
||||
def test_list__json(self):
|
||||
"""List group managed service accounts in json format."""
|
||||
result, out, err = self.runcmd("service-account", "list", "--json")
|
||||
self.assertIsNone(result, msg=err)
|
||||
accounts = json.loads(out)
|
||||
|
||||
self.assertIn("foo$", accounts)
|
||||
self.assertIn("bar$", accounts)
|
||||
self.assertIn("baz$", accounts)
|
||||
|
||||
def test_create(self):
|
||||
"""Create a group managed service account using samba-tool."""
|
||||
# Create a Group Managed Service account using samba-tool.
|
||||
name = self.unique_name()
|
||||
self.create_service_account(name,
|
||||
dns_host_name="test.com",
|
||||
managed_password_interval=60)
|
||||
|
||||
# Group Managed Service count exists.
|
||||
# Since GroupManagedServiceAccount is also a Computer it ends in '$'
|
||||
gmsa = GroupManagedServiceAccount.get(self.samdb, username=name + "$")
|
||||
self.assertIsNotNone(gmsa)
|
||||
self.assertEqual(gmsa.username, name + "$")
|
||||
self.assertEqual(gmsa.dns_host_name, "test.com")
|
||||
self.assertEqual(gmsa.managed_password_interval, 60)
|
||||
|
||||
def test_view(self):
|
||||
"""View a group managed service account using samba-tool."""
|
||||
result, out, err = self.runcmd("service-account", "view",
|
||||
"--name", "foo")
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
# Service account view always returns JSON.
|
||||
response = json.loads(out)
|
||||
self.assertEqual(response["cn"], "foo")
|
||||
self.assertEqual(response["dNSHostName"], "example.com")
|
||||
self.assertEqual(response["msDS-ManagedPasswordInterval"], 30)
|
||||
|
||||
def test_delete(self):
|
||||
"""Delete a group managed service account using samba-tool."""
|
||||
# Create the gmsa without samba-tool.
|
||||
name = self.unique_name()
|
||||
GroupManagedServiceAccount.create(self.samdb, name=name,
|
||||
dns_host_name="example.com"),
|
||||
|
||||
# The group managed service account exists.
|
||||
gmsa = GroupManagedServiceAccount.get(self.samdb, username=name + "$")
|
||||
self.assertIsNotNone(gmsa)
|
||||
|
||||
# Now delete the gmsa.
|
||||
result, out, err = self.runcmd("service-account", "delete",
|
||||
"--name", name)
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
# Service account is gone.
|
||||
gmsa = GroupManagedServiceAccount.get(self.samdb, username=name + "$")
|
||||
self.assertIsNone(gmsa, msg="Group Managed Service Account not deleted.")
|
||||
|
||||
def test_modify(self):
|
||||
"""Modify a group managed service account and manually set SDDL."""
|
||||
name = self.unique_name()
|
||||
gmsa = GroupManagedServiceAccount.create(self.samdb, name=name,
|
||||
dns_host_name="example.com")
|
||||
self.addCleanup(gmsa.delete, self.samdb)
|
||||
|
||||
# Build some SDDL for adding a user manually.
|
||||
bob = User.get(self.samdb, username="bob")
|
||||
sddl = gmsa.group_msa_membership.as_sddl()
|
||||
sddl += f"(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;{bob.object_sid})"
|
||||
|
||||
result, out, err = self.runcmd("service-account", "modify",
|
||||
"--name", name,
|
||||
"--dns-host-name", "new.example.com",
|
||||
"--group-msa-membership", sddl)
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
# Check field changes and see if the new user is in there.
|
||||
gmsa = GroupManagedServiceAccount.get(self.samdb, username=name + "$")
|
||||
self.assertEqual(gmsa.dns_host_name, "new.example.com")
|
||||
self.assertIn(bob.object_sid, gmsa.trustees)
|
||||
|
||||
|
||||
class ServiceAccountGroupMSAMembershipTests(SambaToolCmdTest):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.samdb = cls.getSamDB("-H", HOST, CREDS)
|
||||
super().setUpClass()
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Setup initial data without the samba-tool command."""
|
||||
# Add a user other than the Administrator to the default SDDL.
|
||||
jane = User.get(cls.samdb, username="jane")
|
||||
sddl = f"{GROUP_MSA_MEMBERSHIP_DEFAULT}(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;{jane.object_sid})"
|
||||
cls.gmsa = GroupManagedServiceAccount.create(cls.samdb, name="gmsa",
|
||||
dns_host_name="example.com",
|
||||
group_msa_membership=sddl)
|
||||
|
||||
cls.addClassCleanup(cls.gmsa.delete, cls.samdb)
|
||||
|
||||
@classmethod
|
||||
def _run(cls, *argv):
|
||||
"""Override _run, so we don't always have to pass HOST and CREDS."""
|
||||
args = list(argv)
|
||||
args.extend(["-H", HOST, CREDS])
|
||||
return super()._run(*args)
|
||||
|
||||
runcmd = _run
|
||||
runsubcmd = _run
|
||||
|
||||
def test_show(self):
|
||||
"""Show password viewers on a Group Managed Service Account."""
|
||||
result, out, err = self.runcmd("service-account",
|
||||
"group-msa-membership", "show",
|
||||
"--name", self.gmsa.username)
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
# Plain text output.
|
||||
self.assertIn(
|
||||
"Account-DN: CN=gmsa,CN=Managed Service Accounts,DC=addom,DC=samba,DC=example,DC=com", out)
|
||||
self.assertIn(
|
||||
"CN=Administrator,CN=Users,DC=addom,DC=samba,DC=example,DC=com", out)
|
||||
self.assertIn(
|
||||
"CN=jane,CN=Users,DC=addom,DC=samba,DC=example,DC=com", out)
|
||||
|
||||
def test_show__json(self):
|
||||
"""Show password viewers on a Group Managed Service Account as JSON."""
|
||||
result, out, err = self.runcmd("service-account",
|
||||
"group-msa-membership", "show",
|
||||
"--name", self.gmsa.username,
|
||||
"--json")
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
# JSON output.
|
||||
response = json.loads(out)
|
||||
self.assertEqual(response["dn"], str(self.gmsa.dn))
|
||||
self.assertListEqual(response["trustees"], [
|
||||
"CN=Administrator,CN=Users,DC=addom,DC=samba,DC=example,DC=com",
|
||||
"CN=jane,CN=Users,DC=addom,DC=samba,DC=example,DC=com"
|
||||
])
|
||||
|
||||
def test_add__username(self):
|
||||
"""Add principal to a Group Managed Service Account by username."""
|
||||
alice = User.get(self.samdb, username="alice")
|
||||
name = self.unique_name()
|
||||
gmsa = GroupManagedServiceAccount.create(self.samdb, name=name,
|
||||
dns_host_name="example.com")
|
||||
self.addCleanup(gmsa.delete, self.samdb)
|
||||
|
||||
# Add user 'alice' by username.
|
||||
result, out, err = self.runcmd("service-account",
|
||||
"group-msa-membership", "add",
|
||||
"--name", gmsa.username,
|
||||
"--principal", alice.username)
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
# See if user was added.
|
||||
gmsa.refresh(self.samdb)
|
||||
self.assertIn(alice.object_sid, gmsa.trustees)
|
||||
|
||||
def test_add__dn(self):
|
||||
"""Add principal to a Group Managed Service Account by dn."""
|
||||
admins = Group.get(self.samdb, name="DnsAdmins")
|
||||
name = self.unique_name()
|
||||
gmsa = GroupManagedServiceAccount.create(self.samdb, name=name,
|
||||
dns_host_name="example.com")
|
||||
self.addCleanup(gmsa.delete, self.samdb)
|
||||
|
||||
# Add group 'DnsAdmins' by dn.
|
||||
result, out, err = self.runcmd("service-account",
|
||||
"group-msa-membership", "add",
|
||||
"--name", gmsa.username,
|
||||
"--principal", str(admins.dn))
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
# See if group was added.
|
||||
gmsa.refresh(self.samdb)
|
||||
self.assertIn(admins.object_sid, gmsa.trustees)
|
||||
|
||||
def test_remove__username(self):
|
||||
"""Remove principal from a Group Managed Service Account by username."""
|
||||
# Create a GMSA with custom SDDL and add extra user.
|
||||
bob = User.get(self.samdb, username="bob")
|
||||
sddl = f"{GROUP_MSA_MEMBERSHIP_DEFAULT}(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;{bob.object_sid})"
|
||||
name = self.unique_name()
|
||||
gmsa = GroupManagedServiceAccount.create(self.samdb, name=name,
|
||||
dns_host_name="example.com",
|
||||
group_msa_membership=sddl)
|
||||
|
||||
# The user is in list to start with.
|
||||
self.assertIn(bob.object_sid, gmsa.trustees)
|
||||
|
||||
# Remove user 'bob' by username.
|
||||
result, out, err = self.runcmd("service-account",
|
||||
"group-msa-membership", "remove",
|
||||
"--name", gmsa.username,
|
||||
"--principal", bob.username)
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
# See if user was removed.
|
||||
gmsa.refresh(self.samdb)
|
||||
self.assertNotIn(bob.object_sid, gmsa.trustees)
|
||||
|
||||
def test_remove__dn(self):
|
||||
"""Remove principal from a Group Managed Service Account by dn."""
|
||||
# Create a GMSA with custom SDDL and add extra group.
|
||||
admins = Group.get(self.samdb, name="DnsAdmins")
|
||||
sddl = f"{GROUP_MSA_MEMBERSHIP_DEFAULT}(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;{admins.object_sid})"
|
||||
name = self.unique_name()
|
||||
gmsa = GroupManagedServiceAccount.create(self.samdb, name=name,
|
||||
dns_host_name="example.com",
|
||||
group_msa_membership=sddl)
|
||||
|
||||
# The group is in list to start with.
|
||||
self.assertIn(admins.object_sid, gmsa.trustees)
|
||||
|
||||
# Remove group 'DnsAdmins' by dn.
|
||||
result, out, err = self.runcmd("service-account",
|
||||
"group-msa-membership", "remove",
|
||||
"--name", gmsa.username,
|
||||
"--principal", str(admins.dn))
|
||||
self.assertIsNone(result, msg=err)
|
||||
|
||||
# See if group was removed.
|
||||
gmsa.refresh(self.samdb)
|
||||
self.assertNotIn(admins.object_sid, gmsa.trustees)
|
@ -1170,6 +1170,7 @@ planpythontestsuite("ad_dc_default", "samba.tests.samba_tool.domain_auth_policy"
|
||||
planpythontestsuite("ad_dc_default", "samba.tests.samba_tool.domain_auth_silo")
|
||||
planpythontestsuite("ad_dc_default", "samba.tests.samba_tool.domain_kds_root_key")
|
||||
planpythontestsuite("ad_dc_default", "samba.tests.samba_tool.domain_models")
|
||||
planpythontestsuite("ad_dc_default", "samba.tests.samba_tool.service_account")
|
||||
planpythontestsuite("schema_dc:local", "samba.tests.samba_tool.schema")
|
||||
planpythontestsuite("ad_dc:local", "samba.tests.samba_tool.ntacl")
|
||||
planpythontestsuite("none", "samba.tests.samba_tool.provision_password_check")
|
||||
|
Loading…
x
Reference in New Issue
Block a user