%PDF- %PDF-
| Direktori : /usr/lib/python3/dist-packages/samba/netcmd/domain/auth/ |
| Current File : //usr/lib/python3/dist-packages/samba/netcmd/domain/auth/silo.py |
# Unix SMB/CIFS implementation.
#
# authentication silos - authentication silo management
#
# Copyright (C) Catalyst.Net Ltd. 2023
#
# 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 samba.getopt as options
from samba.netcmd import Command, CommandError, Option, SuperCommand
from samba.netcmd.domain.models import AuthenticationPolicy, AuthenticationSilo
from samba.netcmd.domain.models.exceptions import ModelError
from .silo_member import cmd_domain_auth_silo_member
class cmd_domain_auth_silo_list(Command):
"""List authentication silos on the domain."""
synopsis = "%prog -H <URL> [options]"
takes_optiongroups = {
"sambaopts": options.SambaOptions,
"credopts": options.CredentialsOptions,
}
takes_options = [
Option("-H", "--URL", help="LDB URL for database or target server.",
type=str, metavar="URL", dest="ldap_url"),
Option("--json", help="Output results in JSON format.",
dest="output_format", action="store_const", const="json"),
]
def run(self, ldap_url=None, sambaopts=None, credopts=None,
output_format=None):
ldb = self.ldb_connect(ldap_url, sambaopts, credopts)
# Authentication silos grouped by cn.
try:
silos = {silo.cn: silo.as_dict()
for silo in AuthenticationSilo.query(ldb)}
except ModelError as e:
raise CommandError(e)
# Using json output format gives more detail.
if output_format == "json":
self.print_json(silos)
else:
for silo in silos.keys():
self.outf.write(f"{silo}\n")
class cmd_domain_auth_silo_view(Command):
"""View an authentication silo on the domain."""
synopsis = "%prog -H <URL> [options]"
takes_optiongroups = {
"sambaopts": options.SambaOptions,
"credopts": options.CredentialsOptions,
}
takes_options = [
Option("-H", "--URL", help="LDB URL for database or target server.",
type=str, metavar="URL", dest="ldap_url"),
Option("--name",
help="Name of authentication silo to view (required).",
dest="name", action="store", type=str),
]
def run(self, ldap_url=None, sambaopts=None, credopts=None, name=None):
if not name:
raise CommandError("Argument --name is required.")
ldb = self.ldb_connect(ldap_url, sambaopts, credopts)
try:
silo = AuthenticationSilo.get(ldb, cn=name)
except ModelError as e:
raise CommandError(e)
# Check if silo exists first.
if silo is None:
raise CommandError(f"Authentication silo {name} not found.")
# Display silo as JSON.
self.print_json(silo.as_dict())
class cmd_domain_auth_silo_create(Command):
"""Create a new authentication silo on the domain."""
synopsis = "%prog -H <URL> [options]"
takes_optiongroups = {
"sambaopts": options.SambaOptions,
"credopts": options.CredentialsOptions,
}
takes_options = [
Option("-H", "--URL", help="LDB URL for database or target server.",
type=str, metavar="URL", dest="ldap_url"),
Option("--name", help="Name of authentication silo (required).",
dest="name", action="store", type=str),
Option("--description",
help="Optional description for authentication silo.",
dest="description", action="store", type=str),
Option("--policy",
help="Use single policy for all principals in this silo.",
dest="policy", action="store", type=str),
Option("--user-policy",
help="User account policy.",
dest="user_policy", action="store", type=str),
Option("--service-policy",
help="Managed Service Account policy.",
dest="service_policy", action="store", type=str),
Option("--computer-policy",
help="Computer account policy.",
dest="computer_policy", action="store", type=str),
Option("--protect",
help="Protect authentication silo from accidental deletion.",
dest="protect", action="store_true"),
Option("--unprotect",
help="Unprotect authentication silo from accidental deletion.",
dest="unprotect", action="store_true"),
Option("--audit",
help="Only audit silo policies.",
dest="audit", action="store_true"),
Option("--enforce",
help="Enforce silo policies.",
dest="enforce", action="store_true")
]
@staticmethod
def get_policy(ldb, name):
"""Helper function to fetch auth policy or raise CommandError.
:param ldb: Ldb connection
:param name: Either the DN or name of authentication policy
"""
try:
return AuthenticationPolicy.lookup(ldb, name)
except (LookupError, ValueError) as e:
raise CommandError(e)
def run(self, ldap_url=None, sambaopts=None, credopts=None, name=None,
description=None, policy=None, user_policy=None,
service_policy=None, computer_policy=None, protect=None,
unprotect=None, audit=None, enforce=None):
if not name:
raise CommandError("Argument --name is required.")
if protect and unprotect:
raise CommandError("--protect and --unprotect cannot be used together.")
if audit and enforce:
raise CommandError("--audit and --enforce cannot be used together.")
# If --policy is present start with that as the base. Then optionally
# --user-policy, --service-policy, --computer-policy can override this.
if policy is not None:
user_policy = user_policy or policy
service_policy = service_policy or policy
computer_policy = computer_policy or policy
ldb = self.ldb_connect(ldap_url, sambaopts, credopts)
try:
silo = AuthenticationSilo.get(ldb, cn=name)
except ModelError as e:
raise CommandError(e)
# Make sure silo doesn't already exist.
if silo is not None:
raise CommandError(f"Authentication silo {name} already exists.")
# New silo object.
silo = AuthenticationSilo(cn=name, description=description)
# Set user policy
if user_policy:
silo.user_policy = self.get_policy(ldb, user_policy).dn
# Set service policy
if service_policy:
silo.service_policy = self.get_policy(ldb, service_policy).dn
# Set computer policy
if computer_policy:
silo.computer_policy = self.get_policy(ldb, computer_policy).dn
# Either --enforce will be set or --audit but never both.
# The default if both are missing is enforce=True.
if enforce is not None:
silo.enforced = enforce
else:
silo.enforced = not audit
# Create silo
try:
silo.save(ldb)
if protect:
silo.protect(ldb)
except ModelError as e:
raise CommandError(e)
# Authentication silo created successfully.
self.outf.write(f"Created authentication silo: {name}\n")
class cmd_domain_auth_silo_modify(Command):
"""Modify an authentication silo on the domain."""
synopsis = "%prog -H <URL> [options]"
takes_optiongroups = {
"sambaopts": options.SambaOptions,
"credopts": options.CredentialsOptions,
}
takes_options = [
Option("-H", "--URL", help="LDB URL for database or target server.",
type=str, metavar="URL", dest="ldap_url"),
Option("--name", help="Name of authentication silo (required).",
dest="name", action="store", type=str),
Option("--description",
help="Optional description for authentication silo.",
dest="description", action="store", type=str),
Option("--policy",
help="Set single policy for all principals in this silo.",
dest="policy", action="store", type=str),
Option("--user-policy",
help="Set User account policy.",
dest="user_policy", action="store", type=str),
Option("--service-policy",
help="Set Managed Service Account policy.",
dest="service_policy", action="store", type=str),
Option("--computer-policy",
help="Set Computer Account policy.",
dest="computer_policy", action="store", type=str),
Option("--protect",
help="Protect authentication silo from accidental deletion.",
dest="protect", action="store_true"),
Option("--unprotect",
help="Unprotect authentication silo from accidental deletion.",
dest="unprotect", action="store_true"),
Option("--audit",
help="Only audit silo policies.",
dest="audit", action="store_true"),
Option("--enforce",
help="Enforce silo policies.",
dest="enforce", action="store_true")
]
@staticmethod
def get_policy(ldb, name):
"""Helper function to fetch auth policy or raise CommandError.
:param ldb: Ldb connection
:param name: Either the DN or name of authentication policy
"""
try:
return AuthenticationPolicy.lookup(ldb, name)
except (LookupError, ModelError, ValueError) as e:
raise CommandError(e)
def run(self, ldap_url=None, sambaopts=None, credopts=None, name=None,
description=None, policy=None, user_policy=None,
service_policy=None, computer_policy=None, protect=None,
unprotect=None, audit=None, enforce=None):
if not name:
raise CommandError("Argument --name is required.")
if audit and enforce:
raise CommandError("--audit and --enforce cannot be used together.")
if protect and unprotect:
raise CommandError("--protect and --unprotect cannot be used together.")
# If --policy is set then start with that for all policies.
# They can be individually overridden as well after that.
if policy is not None:
user_policy = user_policy or policy
service_policy = service_policy or policy
computer_policy = computer_policy or policy
ldb = self.ldb_connect(ldap_url, sambaopts, credopts)
try:
silo = AuthenticationSilo.get(ldb, cn=name)
except ModelError as e:
raise CommandError(e)
# Check if silo exists first.
if silo is None:
raise CommandError(f"Authentication silo {name} not found.")
# Either --enforce will be set or --audit but never both.
if enforce:
silo.enforced = True
elif audit:
silo.enforced = False
# Update the description.
if description is not None:
silo.description = description
# Set or unset user policy.
if user_policy == "":
silo.user_policy = None
elif user_policy:
silo.user_policy = self.get_policy(ldb, user_policy).dn
# Set or unset service policy.
if service_policy == "":
silo.service_policy = None
elif service_policy:
silo.service_policy = self.get_policy(ldb, service_policy).dn
# Set or unset computer policy.
if computer_policy == "":
silo.computer_policy = None
elif computer_policy:
silo.computer_policy = self.get_policy(ldb, computer_policy).dn
# Update silo
try:
silo.save(ldb)
if protect:
silo.protect(ldb)
elif unprotect:
silo.unprotect(ldb)
except ModelError as e:
raise CommandError(e)
# Silo updated successfully.
self.outf.write(f"Updated authentication silo: {name}\n")
class cmd_domain_auth_silo_delete(Command):
"""Delete an authentication silo on the domain."""
synopsis = "%prog -H <URL> [options]"
takes_optiongroups = {
"sambaopts": options.SambaOptions,
"credopts": options.CredentialsOptions,
}
takes_options = [
Option("-H", "--URL", help="LDB URL for database or target server.",
type=str, metavar="URL", dest="ldap_url"),
Option("--name", help="Name of authentication silo (required).",
dest="name", action="store", type=str),
Option("--force", help="Force delete protected authentication silo.",
dest="force", action="store_true")
]
def run(self, ldap_url=None, sambaopts=None, credopts=None, name=None,
force=None):
if not name:
raise CommandError("Argument --name is required.")
ldb = self.ldb_connect(ldap_url, sambaopts, credopts)
try:
silo = AuthenticationSilo.get(ldb, cn=name)
except ModelError as e:
raise CommandError(e)
# Check if silo exists first.
if silo is None:
raise CommandError(f"Authentication silo {name} not found.")
# Delete silo
try:
if force:
silo.unprotect(ldb)
silo.delete(ldb)
except ModelError as e:
if not force:
raise CommandError(
f"{e}\nTry --force to delete protected authentication silos.")
else:
raise CommandError(e)
# Authentication silo deleted successfully.
self.outf.write(f"Deleted authentication silo: {name}\n")
class cmd_domain_auth_silo(SuperCommand):
"""Manage authentication silos on the domain."""
subcommands = {
"list": cmd_domain_auth_silo_list(),
"view": cmd_domain_auth_silo_view(),
"create": cmd_domain_auth_silo_create(),
"modify": cmd_domain_auth_silo_modify(),
"delete": cmd_domain_auth_silo_delete(),
"member": cmd_domain_auth_silo_member(),
}