3 # Unix SMB/CIFS implementation.
4 # provision a Samba4 server
5 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007-2008
6 # Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
8 # Based on the original in EJS:
9 # Copyright (C) Andrew Tridgell 2005
11 # This program is free software; you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation; either version 3 of the License, or
14 # (at your option) any later version.
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
21 # You should have received a copy of the GNU General Public License
22 # along with this program. If not, see <http://www.gnu.org/licenses/>.
30 # Find right directory when running from source tree
31 sys
.path
.insert(0, "bin/python")
36 from samba
.credentials
import DONT_USE_KERBEROS
37 from samba
.auth
import system_session
38 import samba
.getopt
as options
39 from samba
.provision
import (
46 from samba
.dsdb
import (
47 DS_DOMAIN_FUNCTION_2000
,
48 DS_DOMAIN_FUNCTION_2003
,
49 DS_DOMAIN_FUNCTION_2008
,
50 DS_DOMAIN_FUNCTION_2008_R2
,
53 # how do we make this case insensitive??
55 parser
= optparse
.OptionParser("provision [options]")
56 sambaopts
= options
.SambaOptions(parser
)
57 parser
.add_option_group(sambaopts
)
58 parser
.add_option_group(options
.VersionOptions(parser
))
59 credopts
= options
.CredentialsOptions(parser
)
60 parser
.add_option_group(credopts
)
61 parser
.add_option("--interactive", help="Ask for names", action
="store_true")
62 parser
.add_option("--domain", type="string", metavar
="DOMAIN",
64 parser
.add_option("--domain-guid", type="string", metavar
="GUID",
65 help="set domainguid (otherwise random)")
66 parser
.add_option("--domain-sid", type="string", metavar
="SID",
67 help="set domainsid (otherwise random)")
68 parser
.add_option("--ntds-guid", type="string", metavar
="GUID",
69 help="set NTDS object GUID (otherwise random)")
70 parser
.add_option("--invocationid", type="string", metavar
="GUID",
71 help="set invocationid (otherwise random)")
72 parser
.add_option("--host-name", type="string", metavar
="HOSTNAME",
74 parser
.add_option("--host-ip", type="string", metavar
="IPADDRESS",
75 help="set IPv4 ipaddress")
76 parser
.add_option("--host-ip6", type="string", metavar
="IP6ADDRESS",
77 help="set IPv6 ipaddress")
78 parser
.add_option("--adminpass", type="string", metavar
="PASSWORD",
79 help="choose admin password (otherwise random)")
80 parser
.add_option("--krbtgtpass", type="string", metavar
="PASSWORD",
81 help="choose krbtgt password (otherwise random)")
82 parser
.add_option("--machinepass", type="string", metavar
="PASSWORD",
83 help="choose machine password (otherwise random)")
84 parser
.add_option("--dns-backend", type="choice", metavar
="NAMESERVER-BACKEND",
85 choices
=["SAMBA_INTERNAL", "BIND9_FLATFILE", "BIND9_DLZ", "NONE"],
86 help="The DNS server backend. SAMBA_INTERNAL is the builtin name server, " \
87 "BIND9_FLATFILE uses bind9 text database to store zone information, " \
88 "BIND9_DLZ uses samba4 AD to store zone information (default), " \
89 "NONE skips the DNS setup entirely (not recommended)",
91 parser
.add_option("--dnspass", type="string", metavar
="PASSWORD",
92 help="choose dns password (otherwise random)")
93 parser
.add_option("--ldapadminpass", type="string", metavar
="PASSWORD",
94 help="choose password to set between Samba and it's LDAP backend (otherwise random)")
95 parser
.add_option("--root", type="string", metavar
="USERNAME",
96 help="choose 'root' unix username")
97 parser
.add_option("--nobody", type="string", metavar
="USERNAME",
98 help="choose 'nobody' user")
99 parser
.add_option("--wheel", type="string", metavar
="GROUPNAME",
100 help="choose 'wheel' privileged group")
101 parser
.add_option("--users", type="string", metavar
="GROUPNAME",
102 help="choose 'users' group")
103 parser
.add_option("--quiet", help="Be quiet", action
="store_true")
104 parser
.add_option("--blank", action
="store_true",
105 help="do not add users or groups, just the structure")
106 parser
.add_option("--ldap-backend-type", type="choice", metavar
="LDAP-BACKEND-TYPE",
107 help="Test initialisation support for unsupported LDAP backend type (fedora-ds or openldap) DO NOT USE",
108 choices
=["fedora-ds", "openldap"])
109 parser
.add_option("--server-role", type="choice", metavar
="ROLE",
110 choices
=["domain controller", "dc", "member server", "member", "standalone"],
111 help="The server role (domain controller | dc | member server | member | standalone). Default is dc.",
112 default
="domain controller")
113 parser
.add_option("--function-level", type="choice", metavar
="FOR-FUN-LEVEL",
114 choices
=["2000", "2003", "2008", "2008_R2"],
115 help="The domain and forest function level (2000 | 2003 | 2008 | 2008_R2 - always native). Default is (Windows) 2003 Native.",
117 parser
.add_option("--next-rid", type="int", metavar
="NEXTRID", default
=1000,
118 help="The initial nextRid value (only needed for upgrades). Default is 1000.")
119 parser
.add_option("--partitions-only",
120 help="Configure Samba's partitions, but do not modify them (ie, join a BDC)", action
="store_true")
121 parser
.add_option("--targetdir", type="string", metavar
="DIR",
122 help="Set target directory")
123 parser
.add_option("--ol-mmr-urls", type="string", metavar
="LDAPSERVER",
124 help="List of LDAP-URLS [ ldap://<FQHN>:<PORT>/ (where <PORT> has to be different than 389!) ] separated with comma (\",\") for use with OpenLDAP-MMR (Multi-Master-Replication), e.g.: \"ldap://s4dc1:9000,ldap://s4dc2:9000\"")
125 parser
.add_option("--use-xattrs", type="choice", choices
=["yes", "no", "auto"], help="Define if we should use the native fs capabilities or a tdb file for storing attributes likes ntacl, auto tries to make an inteligent guess based on the user rights and system capabilities", default
="auto")
126 parser
.add_option("--use-ntvfs", action
="store_true", help="Use NTVFS for the fileserver (default = no)")
127 parser
.add_option("--use-rfc2307", action
="store_true", help="Use AD to store posix attributes (default = no)")
129 opts
= parser
.parse_args()[0]
131 logger
= logging
.getLogger("provision")
132 logger
.addHandler(logging
.StreamHandler(sys
.stdout
))
134 logger
.setLevel(logging
.WARNING
)
136 logger
.setLevel(logging
.INFO
)
138 if len(sys
.argv
) == 1:
139 opts
.interactive
= True
142 from getpass
import getpass
145 def ask(prompt
, default
=None):
146 if default
is not None:
147 print "%s [%s]: " % (prompt
, default
),
149 print "%s: " % (prompt
,),
150 return sys
.stdin
.readline().rstrip("\n") or default
152 default
= socket
.getfqdn().split(".", 1)[1].upper()
155 opts
.realm
= ask("Realm", default
)
156 if opts
.realm
in (None, ""):
157 print >>sys
.stderr
, "No realm set!"
161 default
= opts
.realm
.split(".")[0]
164 opts
.domain
= ask("Domain", default
)
165 if opts
.domain
is None:
166 print >> sys
.stderr
, "No domain set!"
169 opts
.server_role
= ask("Server Role (dc, member, standalone)", "dc")
171 opts
.dns_backend
= ask("DNS backend (SAMBA_INTERNAL, BIND9_FLATFILE, BIND9_DLZ, NONE)", "BIND9_DLZ")
172 if opts
.dns_backend
in (None, ''):
173 print >> sys
.stderr
, "No DNS backend set!"
177 adminpass
= getpass("Administrator password: ")
179 print >>sys
.stderr
, "Invalid administrator password."
181 adminpassverify
= getpass("Retype password: ")
182 if not adminpass
== adminpassverify
:
183 print >>sys
.stderr
, "Sorry, passwords do not match."
185 opts
.adminpass
= adminpass
189 if opts
.realm
in (None, ""):
190 opts
.realm
= sambaopts
._lp
.get('realm')
191 if opts
.realm
is None or opts
.domain
is None:
192 if opts
.realm
is None:
193 print >>sys
.stderr
, "No realm set!"
194 if opts
.domain
is None:
195 print >> sys
.stderr
, "No domain set!"
199 if not opts
.adminpass
:
200 logger
.info("Administrator password will be set randomly!")
202 lp
= sambaopts
.get_loadparm()
203 smbconf
= lp
.configfile
205 if opts
.function_level
== "2000":
206 dom_for_fun_level
= DS_DOMAIN_FUNCTION_2000
207 elif opts
.function_level
== "2003":
208 dom_for_fun_level
= DS_DOMAIN_FUNCTION_2003
209 elif opts
.function_level
== "2008":
210 dom_for_fun_level
= DS_DOMAIN_FUNCTION_2008
211 elif opts
.function_level
== "2008_R2":
212 dom_for_fun_level
= DS_DOMAIN_FUNCTION_2008_R2
214 creds
= credopts
.get_credentials(lp
)
216 creds
.set_kerberos_state(DONT_USE_KERBEROS
)
218 samdb_fill
= FILL_FULL
220 samdb_fill
= FILL_NT4SYNC
221 elif opts
.partitions_only
:
222 samdb_fill
= FILL_DRS
224 if opts
.targetdir
is not None:
225 if not os
.path
.isdir(opts
.targetdir
):
226 os
.mkdir(opts
.targetdir
)
230 if opts
.use_xattrs
== "yes":
232 elif opts
.use_xattrs
== "auto" and not lp
.get("posix:eadb"):
234 file = tempfile
.NamedTemporaryFile(dir=os
.path
.abspath(opts
.targetdir
))
236 file = tempfile
.NamedTemporaryFile(dir=os
.path
.abspath(os
.path
.dirname(lp
.get("private dir"))))
239 samba
.ntacls
.setntacl(lp
, file.name
,
240 "O:S-1-5-32G:S-1-5-32", "S-1-5-32", "native")
243 logger
.info("You are not root or your system do not support xattr, using tdb backend for attributes. ")
248 logger
.info("not using extended attributes to store ACLs and other metadata. If you intend to use this provision in production, rerun the script as root on a system supporting xattrs.")
250 session
= system_session()
252 result
= provision(logger
,
253 session
, creds
, smbconf
=smbconf
, targetdir
=opts
.targetdir
,
254 samdb_fill
=samdb_fill
, realm
=opts
.realm
, domain
=opts
.domain
,
255 domainguid
=opts
.domain_guid
, domainsid
=opts
.domain_sid
,
256 hostname
=opts
.host_name
,
257 hostip
=opts
.host_ip
, hostip6
=opts
.host_ip6
,
258 ntdsguid
=opts
.ntds_guid
,
259 invocationid
=opts
.invocationid
, adminpass
=opts
.adminpass
,
260 krbtgtpass
=opts
.krbtgtpass
, machinepass
=opts
.machinepass
,
261 dns_backend
=opts
.dns_backend
,
262 dnspass
=opts
.dnspass
, root
=opts
.root
, nobody
=opts
.nobody
,
263 wheel
=opts
.wheel
, users
=opts
.users
,
264 serverrole
=opts
.server_role
, dom_for_fun_level
=dom_for_fun_level
,
265 backend_type
=opts
.ldap_backend_type
,
266 ldapadminpass
=opts
.ldapadminpass
, ol_mmr_urls
=opts
.ol_mmr_urls
,
267 useeadb
=eadb
, next_rid
=opts
.next_rid
, lp
=lp
, use_ntvfs
=(opts
.use_ntvfs
),
268 use_rfc2307
=(opts
.use_rfc2307
))
269 except ProvisioningError
, e
:
273 result
.report_logger(logger
)