netcmd: models: gmsa move GroupManagedServiceAccount model to gmsa.py
authorRob van der Linde <rob@catalyst.net.nz>
Thu, 22 Feb 2024 02:47:30 +0000 (15:47 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 1 Mar 2024 04:45:36 +0000 (04:45 +0000)
It needs to inherit from the Computer model, the Computer model also inherits from User.

First, moving it to its own file from user.py to gmsa.py

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>
python/samba/netcmd/domain/models/__init__.py
python/samba/netcmd/domain/models/gmsa.py [new file with mode: 0644]
python/samba/netcmd/domain/models/user.py

index 575a108a3124aa91c05c0ca38e302793449743e6..8051a5c36482d55cc064c0b7b0e21fad76f042c4 100644 (file)
@@ -25,6 +25,7 @@ from .auth_policy import (AuthenticationPolicy, StrongNTLMPolicy,
 from .auth_silo import AuthenticationSilo
 from .claim_type import ClaimType
 from .computer import Computer
+from .gmsa import GroupManagedServiceAccount
 from .group import Group
 from .model import MODELS
 from .schema import AttributeSchema, ClassSchema
@@ -32,5 +33,5 @@ from .site import Site
 from .subnet import Subnet
 from .types import (AccountType, GroupType, SupportedEncryptionTypes,
                     SystemFlags, UserAccountControl)
-from .user import User, GroupManagedServiceAccount
+from .user import User
 from .value_type import ValueType
diff --git a/python/samba/netcmd/domain/models/gmsa.py b/python/samba/netcmd/domain/models/gmsa.py
new file mode 100644 (file)
index 0000000..dde1c0c
--- /dev/null
@@ -0,0 +1,95 @@
+# Unix SMB/CIFS implementation.
+#
+# GroupManagedServiceAccount model.
+#
+# 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/>.
+#
+
+from ldb import Dn
+
+from samba.dcerpc import security
+from samba.dsdb import DS_GUID_MANAGED_SERVICE_ACCOUNTS_CONTAINER
+
+from .exceptions import FieldError
+from .fields import BinaryField, EnumField, IntegerField, SDDLField, StringField
+from .types import SupportedEncryptionTypes
+from .user import User
+
+
+class GroupManagedServiceAccount(User):
+    """A GroupManagedServiceAccount is a type of User with additional fields."""
+    managed_password_interval = IntegerField("msDS-ManagedPasswordInterval")
+    dns_host_name = StringField("dNSHostName")
+    group_msa_membership = SDDLField("msDS-GroupMSAMembership",
+                                     default="O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;LA)")
+    managed_password_id = BinaryField("msDS-ManagedPasswordId",
+                                      readonly=True, hidden=True)
+    managed_password_previous_id = BinaryField("msDS-ManagedPasswordPreviousId",
+                                               readonly=True, hidden=True)
+    supported_encryption_types = EnumField("msDS-SupportedEncryptionTypes",
+                                           SupportedEncryptionTypes)
+
+    @staticmethod
+    def get_base_dn(ldb):
+        """Return base Dn for Managed Service Accounts.
+
+        :param ldb: Ldb connection
+        :return: Dn to use for searching
+        """
+        return ldb.get_wellknown_dn(ldb.get_default_basedn(),
+                                    DS_GUID_MANAGED_SERVICE_ACCOUNTS_CONTAINER)
+
+    @staticmethod
+    def get_object_class():
+        return "msDS-GroupManagedServiceAccount"
+
+    @property
+    def trustees(self):
+        """Returns list of trustees from the msDS-GroupMSAMembership field.
+
+        :return: list of SID strings
+        """
+        allowed = []
+
+        # Make sure to exclude DENY aces.
+        for ace in self.group_msa_membership.dacl.aces:
+            if ((ace.access_mask & security.SEC_ADS_READ_PROP)
+                    and ace.type == security.SEC_ACE_TYPE_ACCESS_ALLOWED):
+                allowed.append(str(ace.trustee))
+            else:
+                raise FieldError(
+                    "Cannot be represented as a simple list (try viewing as SDDL)",
+                    field=GroupManagedServiceAccount.group_msa_membership)
+
+        return allowed
+
+    @classmethod
+    def find(cls, ldb, name):
+        """Helper function to find a service account first by Dn then username.
+
+        If the Dn can't be parsed use sAMAccountName, automatically add the $.
+        """
+        try:
+            query = {"dn": Dn(ldb, name)}
+        except ValueError:
+            if name.endswith("$"):
+                query = {"username": name}
+            else:
+                query = {"username": name + "$"}
+
+        return cls.get(ldb, **query)
index ebd45b7491aa108b809eb5531f14b58cae8a03dd..f934f7b33359e1b7484d7b5a608ff11e676eb604 100644 (file)
 
 from ldb import Dn
 
-from samba.dcerpc import security
-from samba.dsdb import (DS_GUID_MANAGED_SERVICE_ACCOUNTS_CONTAINER,
-                        DS_GUID_USERS_CONTAINER)
+from samba.dsdb import DS_GUID_USERS_CONTAINER
 
-from .exceptions import FieldError
-from .fields import (BinaryField, DnField, EnumField, IntegerField, SDDLField,
-                     SIDField, StringField, NtTimeField)
+from .fields import (DnField, EnumField, IntegerField, SIDField, StringField,
+                     NtTimeField)
 from .model import Model
-from .types import AccountType, SupportedEncryptionTypes, UserAccountControl
+from .types import AccountType, UserAccountControl
 
 
 class User(Model):
@@ -93,67 +90,3 @@ class User(Model):
             query = {"username": name}
 
         return cls.get(ldb, **query)
-
-
-class GroupManagedServiceAccount(User):
-    """A GroupManagedServiceAccount is a type of User with additional fields."""
-    managed_password_interval = IntegerField("msDS-ManagedPasswordInterval")
-    dns_host_name = StringField("dNSHostName")
-    group_msa_membership = SDDLField("msDS-GroupMSAMembership",
-                                     default="O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;LA)")
-    managed_password_id = BinaryField("msDS-ManagedPasswordId",
-                                      readonly=True, hidden=True)
-    managed_password_previous_id = BinaryField("msDS-ManagedPasswordPreviousId",
-                                               readonly=True, hidden=True)
-    supported_encryption_types = EnumField("msDS-SupportedEncryptionTypes",
-                                           SupportedEncryptionTypes)
-
-    @staticmethod
-    def get_base_dn(ldb):
-        """Return base Dn for Managed Service Accounts.
-
-        :param ldb: Ldb connection
-        :return: Dn to use for searching
-        """
-        return ldb.get_wellknown_dn(ldb.get_default_basedn(),
-                                    DS_GUID_MANAGED_SERVICE_ACCOUNTS_CONTAINER)
-
-    @staticmethod
-    def get_object_class():
-        return "msDS-GroupManagedServiceAccount"
-
-    @property
-    def trustees(self):
-        """Returns list of trustees from the msDS-GroupMSAMembership field.
-
-        :return: list of SID strings
-        """
-        allowed = []
-
-        # Make sure to exclude DENY aces.
-        for ace in self.group_msa_membership.dacl.aces:
-            if ((ace.access_mask & security.SEC_ADS_READ_PROP)
-                    and ace.type == security.SEC_ACE_TYPE_ACCESS_ALLOWED):
-                allowed.append(str(ace.trustee))
-            else:
-                raise FieldError(
-                    "Cannot be represented as a simple list (try viewing as SDDL)",
-                    field=GroupManagedServiceAccount.group_msa_membership)
-
-        return allowed
-
-    @classmethod
-    def find(cls, ldb, name):
-        """Helper function to find a service account first by Dn then username.
-
-        If the Dn can't be parsed use sAMAccountName, automatically add the $.
-        """
-        try:
-            query = {"dn": Dn(ldb, name)}
-        except ValueError:
-            if name.endswith("$"):
-                query = {"username": name}
-            else:
-                query = {"username": name + "$"}
-
-        return cls.get(ldb, **query)