1 # Unix SMB/CIFS implementation.
3 # Manage service accounts and group managed service accounts.
5 # Copyright (C) Catalyst.Net Ltd. 2024
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/>.
23 from samba
.domain
.models
import GroupManagedServiceAccount
24 from samba
.domain
.models
.exceptions
import ModelError
25 from samba
.getopt
import CredentialsOptions
, HostOptions
, Option
, SambaOptions
26 from samba
.netcmd
import Command
, CommandError
29 class cmd_service_account_list(Command
):
30 """List service accounts."""
32 synopsis
= "%prog -H <URL> [options]"
34 takes_optiongroups
= {
35 "sambaopts": SambaOptions
,
36 "credopts": CredentialsOptions
,
37 "hostopts": HostOptions
,
41 Option("--json", help="Output results in JSON format.",
42 dest
="output_format", action
="store_const", const
="json"),
45 def run(self
, hostopts
=None, sambaopts
=None, credopts
=None,
48 ldb
= self
.ldb_connect(hostopts
, sambaopts
, credopts
)
51 accounts
= GroupManagedServiceAccount
.query(ldb
)
52 except ModelError
as e
:
55 if output_format
== "json":
56 self
.print_json({account
.account_name
: account
for account
in accounts
})
58 for account
in accounts
:
59 print(account
.account_name
, file=self
.outf
)
62 class cmd_service_account_view(Command
):
63 """View a service account on the domain."""
65 synopsis
= "%prog -H <URL> [options]"
67 takes_optiongroups
= {
68 "sambaopts": SambaOptions
,
69 "credopts": CredentialsOptions
,
70 "hostopts": HostOptions
,
75 help="Name of managed service account (required).",
76 dest
="name", action
="store", type=str, required
=True),
79 def run(self
, hostopts
=None, sambaopts
=None, credopts
=None, name
=None):
81 ldb
= self
.ldb_connect(hostopts
, sambaopts
, credopts
)
84 account
= GroupManagedServiceAccount
.find(ldb
, name
)
85 except ModelError
as e
:
89 raise CommandError(f
"Group managed service account {name} not found.")
91 self
.print_json(account
.as_dict())
94 class cmd_service_account_create(Command
):
95 """Create a new service account."""
97 synopsis
= "%prog -H <URL> [options]"
99 takes_optiongroups
= {
100 "sambaopts": SambaOptions
,
101 "credopts": CredentialsOptions
,
102 "hostopts": HostOptions
,
106 Option("--name", help="Name of managed service account (required).",
107 dest
="name", action
="store", type=str, required
=True),
108 Option("--dns-host-name", help="DNS hostname of this service account (required).",
109 dest
="dns_host_name", action
="store", type=str, required
=True),
110 Option("--group-msa-membership",
111 help="Provide optional Group MSA Membership SDDL.",
112 dest
="group_msa_membership", action
="store", type=str),
113 Option("--managed-password-interval",
114 help="Managed password refresh interval in days.",
115 dest
="managed_password_interval", action
="store", type=int),
118 def run(self
, hostopts
=None, sambaopts
=None, credopts
=None, name
=None,
119 dns_host_name
=None, group_msa_membership
=None,
120 managed_password_interval
=None):
122 ldb
= self
.ldb_connect(hostopts
, sambaopts
, credopts
)
124 gmsa
= GroupManagedServiceAccount(
126 managed_password_interval
=managed_password_interval
,
127 dns_host_name
=dns_host_name
,
128 group_msa_membership
=group_msa_membership
,
131 # Create group managed service account.
134 except ModelError
as e
:
135 raise CommandError(e
)
137 print(f
"Created group managed service account: {name}", file=self
.outf
)
140 class cmd_service_account_modify(Command
):
141 """Modify a managed service account."""
143 synopsis
= "%prog -H <URL> [options]"
145 takes_optiongroups
= {
146 "sambaopts": SambaOptions
,
147 "credopts": CredentialsOptions
,
148 "hostopts": HostOptions
,
152 Option("--name", help="Name of managed service account (required).",
153 dest
="name", action
="store", type=str, required
=True),
154 Option("--dns-host-name", help="Update DNS hostname of this service account.",
155 dest
="dns_host_name", action
="store", type=str),
156 Option("--group-msa-membership",
157 help="Update Group MSA Membership field directly (SDDL).",
158 dest
="group_msa_membership", action
="store", type=str),
161 def run(self
, hostopts
=None, sambaopts
=None, credopts
=None, name
=None,
162 dns_host_name
=None, group_msa_membership
=None):
164 ldb
= self
.ldb_connect(hostopts
, sambaopts
, credopts
)
167 gmsa
= GroupManagedServiceAccount
.find(ldb
, name
)
168 except ModelError
as e
:
169 raise CommandError(e
)
172 raise CommandError(f
"Group managed service account {name} not found.")
174 if dns_host_name
is not None:
175 gmsa
.dns_host_name
= dns_host_name
177 if group_msa_membership
is not None:
178 gmsa
.group_msa_membership
= group_msa_membership
180 # Update group managed service account.
183 except ModelError
as e
:
184 raise CommandError(e
)
186 print(f
"Modified group managed service account: {name}", file=self
.outf
)
189 class cmd_service_account_delete(Command
):
190 """Delete a managed service account."""
192 synopsis
= "%prog -H <URL> [options]"
194 takes_optiongroups
= {
195 "sambaopts": SambaOptions
,
196 "credopts": CredentialsOptions
,
197 "hostopts": HostOptions
,
201 Option("--name", help="Name of managed service account (required).",
202 dest
="name", action
="store", type=str, required
=True),
205 def run(self
, hostopts
=None, sambaopts
=None, credopts
=None, name
=None):
207 ldb
= self
.ldb_connect(hostopts
, sambaopts
, credopts
)
210 account
= GroupManagedServiceAccount
.find(ldb
, name
)
211 except ModelError
as e
:
212 raise CommandError(e
)
215 raise CommandError(f
"Group managed service account {name} not found.")
219 except ModelError
as e
:
220 raise CommandError(e
)
222 print(f
"Deleted group managed service account: {name}", file=self
.outf
)