# Unix SMB/CIFS implementation. # # manage assigned authentication silos on a user # # Copyright (C) Catalyst.Net Ltd. 2023 # # Written by Rob van der Linde # # 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 . # import samba.getopt as options from samba.netcmd import Command, CommandError, Option, SuperCommand from samba.netcmd.domain.models import AuthenticationSilo, User from samba.netcmd.domain.models.exceptions import ModelError class cmd_user_auth_silo_assign(Command): """Set the assigned authentication silo on a user.""" synopsis = "%prog [options]" takes_args = ["username"] takes_optiongroups = { "sambaopts": options.SambaOptions, "credopts": options.CredentialsOptions, "hostopts": options.HostOptions, } takes_options = [ Option("--silo", help="Authentication silo name.", action="store", dest="silo_name", type=str, required=True), ] def run(self, username, hostopts=None, sambaopts=None, credopts=None, silo_name=None): ldb = self.ldb_connect(hostopts, sambaopts, credopts) try: user = User.find(ldb, username) silo = AuthenticationSilo.get(ldb, name=silo_name) except ModelError as e: raise CommandError(e) # User and silo exist. if user is None: raise CommandError(f"User {username} not found.") if silo is None: raise CommandError(f"Authentication silo {silo_name} not found.") # Set assigned silo. user.assigned_silo = silo.dn try: user.save(ldb) except ModelError as e: raise CommandError(f"Set assigned authentication silo failed: {e}") # Display silo member status. if user.dn in silo.members: status = "granted" else: status = "revoked" print(f"User {username} assigned to authentication silo {silo} ({status})", file=self.outf) class cmd_user_auth_silo_remove(Command): """Remove the assigned authentication silo on a user.""" synopsis = "%prog [options]" takes_args = ["username"] takes_optiongroups = { "sambaopts": options.SambaOptions, "credopts": options.CredentialsOptions, "hostopts": options.HostOptions, } def run(self, username, hostopts=None, sambaopts=None, credopts=None): ldb = self.ldb_connect(hostopts, sambaopts, credopts) try: user = User.find(ldb, username) except ModelError as e: raise CommandError(e) # User exists if user is None: raise CommandError(f"User {username} not found.") # Get previous silo for display. if user.assigned_silo: try: silo = AuthenticationSilo.get(ldb, dn=user.assigned_silo) except ModelError as e: raise CommandError(e) else: silo = None # Unset assigned authentication silo user.assigned_silo = None try: user.save(ldb) except ModelError as e: raise CommandError(f"Remove assigned authentication silo failed: {e}") # Display silo member status. if silo and user.dn in silo.members: status = "granted" else: status = "revoked" print(f"User {username} removed from authentication silo {silo} ({status})", file=self.outf) class cmd_user_auth_silo_view(Command): """View the current assigned authentication silo on a user.""" synopsis = "%prog [options]" takes_args = ["username"] takes_optiongroups = { "sambaopts": options.SambaOptions, "credopts": options.CredentialsOptions, "hostopts": options.HostOptions, } def run(self, username, hostopts=None, sambaopts=None, credopts=None): ldb = self.ldb_connect(hostopts, sambaopts, credopts) try: user = User.find(ldb, username) # Check user exists before fetching silo. if user is None: raise CommandError(f"User {username} not found.") # Only fetch silo is one is assigned. if user.assigned_silo: silo = AuthenticationSilo.get(ldb, dn=user.assigned_silo) else: silo = None except ModelError as e: raise CommandError(e) # Display silo member status. if silo and user.dn in silo.members: status = "granted" else: status = "revoked" if silo: print(f"User {username} assigned to authentication silo {silo} ({status})", file=self.outf) else: print(f"User {username} has no assigned authentication silo.", file=self.outf) class cmd_user_auth_silo(SuperCommand): """Manage authentication silos on a user.""" subcommands = { "assign": cmd_user_auth_silo_assign(), "remove": cmd_user_auth_silo_remove(), "view": cmd_user_auth_silo_view(), }