r8347: replace the perl provision script with a ejs script
[tprouty/samba.git] / source4 / setup / provision
1 #!/usr/bin/env smbscript
2 /*
3         provision a Samba4 server
4         Copyright Andrew Tridgell 2005
5         Released under the GNU GPL v2 or later
6 */
7
8 var options = new Object();
9 ok = GetOptions(ARGV, options, 
10                 "POPT_AUTOHELP",
11                 "POPT_COMMON_SAMBA",
12                 "POPT_COMMON_VERSION",
13                 'realm=s',
14                 'domain=s',
15                 'domain-guid=s',
16                 'domain-sid=s',
17                 'host-name=s',
18                 'host-ip=s',
19                 'host-guid=s',
20                 'invocationid=s',
21                 'adminpass=s',
22                 'krbtgtpass=s',
23                 'machinepass=s',
24                 'root=s',
25                 'nobody=s',
26                 'nogroup=s',
27                 'wheel=s',
28                 'users=s',
29                 'outputdir=s',
30                 'quiet');
31 if (ok == false) {
32    println("Failed to parse options: " + options.ERROR);
33    return -1;
34 }
35
36 libinclude("base.js");
37
38 /* used to generate sequence numbers for records */
39 next_usn = 1;
40
41 /*
42   print a message if quiet is not set
43 */
44 function message(s) 
45 {
46         if (options["quiet"] == undefined) {
47                 println(s);
48         }
49 }
50
51 /*
52   find a user or group from a list of possibilities
53 */
54 function findnss()
55 {
56         var i;
57         assert(arguments.length >= 2);
58         var nssfn = arguments[0];
59         var name = arguments[1];
60         if (options[name] != undefined) {
61                 return options[name];
62         }
63         for (i=2;i<arguments.length;i++) {
64                 if (nssfn(arguments[i]) != undefined) {
65                         return arguments[i];
66                 }
67         }
68         println("Unable to find user/group for " + name);
69         exit(1);
70 }
71
72 /*
73    add a foreign security principle
74  */
75 function add_foreign(str, sid, desc, unixname)
76 {
77         var add = "
78 dn: CN=${SID},CN=ForeignSecurityPrincipals,${BASEDN}
79 objectClass: top
80 objectClass: foreignSecurityPrincipal
81 cn: ${SID}
82 description: ${DESC}
83 instanceType: 4
84 whenCreated: ${LDAPTIME}
85 whenChanged: ${LDAPTIME}
86 uSNCreated: 1
87 uSNChanged: 1
88 showInAdvancedViewOnly: TRUE
89 name: ${SID}
90 objectGUID: ${NEWGUID}
91 objectSid: ${SID}
92 objectCategory: CN=Foreign-Security-Principal,CN=Schema,CN=Configuration,${BASEDN}
93 unixName: ${UNIXNAME}
94 ";
95         var sub = new Object();
96         sub.SID = sid;
97         sub.DESC = desc;
98         sub.UNIXNAME = unixname;
99         return str + substitute_var(add, sub);
100 }
101
102 /*
103   return current time as a nt time string
104 */
105 function nttime()
106 {
107         return "" + sys_nttime();
108 }
109
110 /*
111   return current time as a ldap time string
112 */
113 function ldaptime()
114 {
115         return sys_ldaptime(sys_nttime());
116 }
117
118 function datestring()
119 {
120         var t = sys_gmtime(sys_nttime());
121         return sprintf("%04u%02u%02u%02u",
122                        t.tm_year+1900, t.tm_mon+1, t.tm_mday, t.tm_hour);
123 }
124
125 /*
126   return current time as a ldap time string
127 */
128 function nextusn()
129 {
130         next_usn = next_usn+1;
131         return next_usn;
132 }
133
134 /*
135   return first part of hostname
136 */
137 function hostname()
138 {
139         var s = split(".", sys_hostname());
140         return s[0];
141 }
142
143
144 /*
145   setup a ldb in the private dir
146  */
147 function setup_ldb(ldif, dbname, subobj)
148 {
149         var extra = "";
150         if (arguments.length == 4) {
151                 extra = arguments[3];
152         }
153         printVars(lpGet("setup directory"));
154
155         var db = lpGet("private dir") + "/" + dbname;
156         var src = lpGet("setup directory") + "/" + ldif;
157
158         sys_unlink(db);
159
160         var data = sys_file_load(src);
161         data = data + extra;
162         data = substitute_var(data, subobj);
163
164         message("Creating " + db + "\n from " + src);
165         ok = ldbAdd(db, data);
166         assert(ok);
167 }
168
169 /*
170   setup a file in the private dir
171  */
172 function setup_file(template, fname, subobj)
173 {
174         var f = lpGet("private dir") + "/" + fname;
175         var src = lpGet("setup directory") + "/" + template;
176
177         sys_unlink(f);
178
179         var data = sys_file_load(src);
180         data = substitute_var(data, subobj);
181
182         message("Creating " + f + "\n from " + src);
183         ok = sys_file_save(f, data);
184         assert(ok);
185 }
186
187 /*
188  show some help
189 */
190 function ShowHelp()
191 {
192         print("
193 Samba4 provisioning
194
195 provision.pl [options]
196  --realm        REALM           set realm
197  --domain       DOMAIN          set domain
198  --domain-guid  GUID            set domainguid (otherwise random)
199  --domain-sid   SID             set domainsid (otherwise random)
200  --host-name    HOSTNAME        set hostname
201  --host-ip      IPADDRESS       set ipaddress
202  --host-guid    GUID            set hostguid (otherwise random)
203  --invocationid GUID            set invocationid (otherwise random)
204  --outputdir    OUTPUTDIR       set output directory
205  --adminpass    PASSWORD        choose admin password (otherwise random)
206  --krbtgtpass   PASSWORD        choose krbtgt password (otherwise random)
207  --machinepass  PASSWORD        choose machine password (otherwise random)
208  --root         USERNAME        choose 'root' unix username
209  --nobody       USERNAME        choose 'nobody' user
210  --nogroup      GROUPNAME       choose 'nogroup' group
211  --wheel        GROUPNAME       choose 'wheel' privileged group
212  --users        GROUPNAME       choose 'users' group
213  --quiet                        Be quiet
214
215 You must provide at least a realm and domain
216
217 ");
218         exit(1);
219 }
220
221 if (options['host-name'] == undefined) {
222         options['host-name'] = hostname();
223 }
224
225 /*
226    main program
227 */
228 if (options["realm"] == undefined ||
229     options["domain"] == undefined ||
230     options["host-name"] == undefined) {
231         ShowHelp();
232 }
233
234 options.realm        = strlower(options.realm);
235 options['host-name'] = strlower(options['host-name']);
236 options.domain       = strupper(options.domain);
237 options.netbiosname  = strupper(options['host-name']);
238
239 if (options.hostip == undefined) {
240         var list = sys_interfaces();
241         options.hostip = list[0];
242 }
243
244 message("Provisioning for " + options.domain + " in realm " + options.realm);
245
246 options.root    = findnss(getpwnam, "root", "root");
247 options.nobody  = findnss(getpwnam, "nobody", "nobody");
248 options.nogroup = findnss(getgrnam, "nogroup", "nogroup", "nobody");
249 options.wheel   = findnss(getgrnam, "wheel", "wheel", "root");
250 options.users   = findnss(getgrnam, "users", "users", "guest", "other");
251
252
253 options.dnsdomain = strlower(options.realm);
254 options.dnsname   = strlower(options['host-name']) + "." + options.dnsdomain;
255 options.basedn    = "DC=" + join(",DC=", split(".", options.realm));
256
257 /*
258   setup the substitution object
259 */
260 var subobj = new Object();
261 subobj.DOMAINGUID   = randguid();
262 subobj.DOMAINSID    = randsid();
263 subobj.HOSTGUID     = randguid();
264 subobj.INVOCATIONID = randguid();
265 subobj.KRBTGTPASS   = randpass(12);
266 subobj.MACHINEPASS  = randpass(12);
267 subobj.ADMINPASS    = randpass(12);
268 subobj.DEFAULTSITE  = "Default-First-Site-Name";
269 subobj.NEWGUID      = randguid;
270 subobj.NTTIME       = nttime;
271 subobj.LDAPTIME     = ldaptime;
272 subobj.DATESTRING   = datestring;
273 subobj.USN          = nextusn;
274 for (r in options) {
275         var key = strupper(join("", split("-", r)));
276         subobj[key] = options[r];
277 }
278
279
280 var extradata = "";
281 extradata = add_foreign(extradata, "S-1-5-7",  "Anonymous",           "${NOBODY}");
282 extradata = add_foreign(extradata, "S-1-1-0",  "World",               "${NOGROUP}");
283 extradata = add_foreign(extradata, "S-1-5-2",  "Network",             "${NOGROUP}");
284 extradata = add_foreign(extradata, "S-1-5-18", "System",              "${ROOT}");
285 extradata = add_foreign(extradata, "S-1-5-11", "Authenticated Users", "${USERS}");
286
287 message("Using administrator password: " + subobj.ADMINPASS);
288
289 setup_ldb("hklm.ldif", "hklm.ldb", subobj);
290 setup_ldb("provision.ldif", "sam.ldb", subobj, extradata);
291 setup_ldb("rootdse.ldif", "rootdse.ldb", subobj);
292 setup_ldb("secrets.ldif", "secrets.ldb", subobj);
293 setup_file("provision.zone", subobj.DNSDOMAIN + ".zone", subobj);
294
295 message("All OK");
296 return 0;