pac.create
This commit is contained in:
parent
ea8c5d5924
commit
873c2af90f
@ -40,6 +40,19 @@
|
|||||||
<sleep minutes="5"/>
|
<sleep minutes="5"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<target name="jar" depends="enhance">
|
||||||
|
<jar destfile="build/hsar.jar">
|
||||||
|
<fileset dir="build/cls"/>
|
||||||
|
<fileset dir="src">
|
||||||
|
<include name="**/*.properties"/>
|
||||||
|
<include name="**/*.jtpl"/>
|
||||||
|
</fileset>
|
||||||
|
<fileset dir="conf">
|
||||||
|
<include name="**/*.xml"/>
|
||||||
|
</fileset>
|
||||||
|
</jar>
|
||||||
|
</target>
|
||||||
|
|
||||||
<target name="war" depends="enhance">
|
<target name="war" depends="enhance">
|
||||||
<copy file="conf/WEB-INF/web.xml" todir="webapp/WEB-INF/">
|
<copy file="conf/WEB-INF/web.xml" todir="webapp/WEB-INF/">
|
||||||
<filterset>
|
<filterset>
|
||||||
|
@ -144,29 +144,27 @@ public class QueueServer extends QueueCommons implements
|
|||||||
// execute processor within the message
|
// execute processor within the message
|
||||||
task.getProcessor().process();
|
task.getProcessor().process();
|
||||||
System.out.println("done");
|
System.out.println("done");
|
||||||
|
} catch (Throwable throwable) {
|
||||||
// mark done
|
logException(throwable);
|
||||||
sendStatus(task);
|
task.setException(throwable);
|
||||||
} catch (Exception receiveException) {
|
|
||||||
System.err.println("exception " + receiveException); // TODO:
|
|
||||||
// logging
|
|
||||||
receiveException.printStackTrace(System.err);
|
|
||||||
if (receiveException.getCause() != null) {
|
|
||||||
System.err.println("caused by exception "
|
|
||||||
+ receiveException.getCause()); // TODO: logging
|
|
||||||
receiveException.getCause().printStackTrace(System.err);
|
|
||||||
} else
|
|
||||||
System.err.println("no further cause available");
|
|
||||||
task.setException(receiveException);
|
|
||||||
sendStatus(task);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
System.err.println("severe exception " + t); // TODO: logging
|
|
||||||
} finally {
|
} finally {
|
||||||
|
sendStatus(task);
|
||||||
setNMessagesProcessed(getNMessagesProcessed() + 1);
|
setNMessagesProcessed(getNMessagesProcessed() + 1);
|
||||||
notifyAll();
|
notifyAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void logException(Throwable t) {
|
||||||
|
System.err.println("exception " + t); // TODO: logging
|
||||||
|
t.printStackTrace(System.err);
|
||||||
|
if (t.getCause() != null) {
|
||||||
|
System.err.println("caused by exception "
|
||||||
|
+ t.getCause()); // TODO: logging
|
||||||
|
t.getCause().printStackTrace(System.err);
|
||||||
|
} else
|
||||||
|
System.err.println("no further cause available");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onException(JMSException e) {
|
public void onException(JMSException e) {
|
||||||
System.out.println("Exception: " + e.getMessage());
|
System.out.println("Exception: " + e.getMessage());
|
||||||
|
@ -181,15 +181,14 @@ public class QueueTask extends AbstractEntity implements Serializable {
|
|||||||
|
|
||||||
public String getException() {
|
public String getException() {
|
||||||
return exception;
|
return exception;
|
||||||
};
|
}
|
||||||
|
|
||||||
public void setException(String exception) {
|
public void setException(String exception) {
|
||||||
this.exception = exception;
|
this.exception = exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setException(Exception exception) {
|
public void setException(Throwable exception) {
|
||||||
this.exception = exception.toString();
|
this.exception = exception.getMessage();
|
||||||
// TODO: stack+cause
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -6,13 +6,14 @@ import java.io.FileWriter;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.sf.jtpl.Template;
|
import net.sf.jtpl.Template;
|
||||||
|
|
||||||
public class TemplateProcessor extends AbstractProcessor {
|
public class TemplateProcessor extends AbstractProcessor {
|
||||||
|
|
||||||
private static final long serialVersionUID = 4520635523274792876L;
|
private static final long serialVersionUID = 2L;
|
||||||
|
|
||||||
private String content = null;
|
private String content = null;
|
||||||
private String targetPath = null;
|
private String targetPath = null;
|
||||||
@ -34,6 +35,29 @@ public class TemplateProcessor extends AbstractProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TemplateProcessor(String templateName, Map<String, String> mainValues, Iterator<Map<String, String>> iterateValues, String targetPath, boolean overwriteTarget) throws ProcessorException {
|
||||||
|
this.targetPath = targetPath;
|
||||||
|
this.overwriteTarget = overwriteTarget;
|
||||||
|
try {
|
||||||
|
InputStream stream = TemplateProcessor.class.getClassLoader().getResourceAsStream(templateName);
|
||||||
|
Template template = new Template(new InputStreamReader(stream));
|
||||||
|
for (String key : mainValues.keySet()) {
|
||||||
|
template.assign(key, mainValues.get(key));
|
||||||
|
}
|
||||||
|
while (iterateValues.hasNext()) {
|
||||||
|
Map<String, String> iterationValues = iterateValues.next();
|
||||||
|
for (String key : iterationValues.keySet()) {
|
||||||
|
template.assign(key, iterationValues.get(key));
|
||||||
|
}
|
||||||
|
template.parse("main.iterate");
|
||||||
|
}
|
||||||
|
template.parse("main");
|
||||||
|
content = template.out();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ProcessorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object process() throws ProcessorException {
|
public Object process() throws ProcessorException {
|
||||||
try {
|
try {
|
||||||
|
@ -3,6 +3,10 @@ package de.hsadmin.mods.pac;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -46,16 +50,33 @@ public class PacProcessorFactory implements EntityProcessorFactory {
|
|||||||
if (unixUserSet.size() == 1) {
|
if (unixUserSet.size() == 1) {
|
||||||
unixUser = unixUserSet.iterator().next();
|
unixUser = unixUserSet.iterator().next();
|
||||||
}
|
}
|
||||||
Processor hostsAppender = new ShellProcessor("echo '" + inetAddr + " " + pacName +".hostsharing.net " + pacName + "\n' >>/etc/hosts");
|
Hive hive = pac.getHive();
|
||||||
Processor interfacesAppender = new ShellProcessor("echo 'auto eth0:" + pacName + "\n" +
|
Map<String, String> hiveValues = new HashMap<String, String>();
|
||||||
"iface eth0:" + pacName + " inet static\n" +
|
hiveValues.put("HIVE", hive.getName());
|
||||||
"\taddress " + inetAddr + "\n" +
|
String hiveIP = hive.getInetAddr().getInetAddr();
|
||||||
"\tnetmask 255.255.255.0\n\n' >>/etc/network/interfaces");
|
hiveValues.put("HIVE_IP", hiveIP);
|
||||||
Processor sudoersAppender = new ShellProcessor("echo '" + pacName + " ALL = (%" + pacName + ") NOPASSWD: ALL\n' >> /etc/sudoers");
|
hiveValues.put("HIVE_GATEWAY", hiveIP.substring(0, hiveIP.lastIndexOf('.')) + ".1");
|
||||||
|
List<Map<String, String>> pacValuesList = new ArrayList<Map<String, String>>();
|
||||||
|
Set<Pac> pacsSet = hive.getPacs();
|
||||||
|
for (Pac p : pacsSet) {
|
||||||
|
HashMap<String, String> pacValues = new HashMap<String, String>();
|
||||||
|
pacValues.put("PAC", p.getName());
|
||||||
|
pacValues.put("PAC_IP", p.getCurINetAddr().getInetAddr());
|
||||||
|
pacValuesList.add(pacValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
// nicht ausprobiert!
|
||||||
|
|
||||||
|
Processor hostsAppender = new TemplateProcessor("/de/hsadmin/mods/pac/hosts.jtpl", hiveValues, pacValuesList.iterator(), "/etc/hosts", true);
|
||||||
|
Processor interfacesAppender = new TemplateProcessor("/de/hsadmin/mods/pac/interfaces.jtpl", hiveValues, pacValuesList.iterator(), "/etc/network/interfaces", true);
|
||||||
|
Processor sudoersAppender = new TemplateProcessor("/de/hsadmin/mods/pac/sudoers.jtpl", hiveValues, pacValuesList.iterator(), "/etc/sudoers", true);
|
||||||
|
|
||||||
|
// nicht ausprobiert!
|
||||||
|
|
||||||
String password = PwGenerator.generatePassword(7, flagBuilder.build(), 100, random);
|
String password = PwGenerator.generatePassword(7, flagBuilder.build(), 100, random);
|
||||||
Processor newUsersProc = new ShellProcessor(
|
Processor newUsersProc = new ShellProcessor(
|
||||||
"newusers", pacName + ":" + password + ":"
|
"newusers", pacName + ":" + password + ":"
|
||||||
+ unixUser.getUserId() + ":" + unixUser.getPac().getName()
|
+ unixUser.getUserId() + ":" + unixUser.getUserId()
|
||||||
+ ":" + unixUser.getComment() + ":" + unixUser.getHomedir()
|
+ ":" + unixUser.getComment() + ":" + unixUser.getHomedir()
|
||||||
+ ":" + unixUser.getShell() + "\n");
|
+ ":" + unixUser.getShell() + "\n");
|
||||||
try {
|
try {
|
||||||
@ -71,7 +92,10 @@ public class PacProcessorFactory implements EntityProcessorFactory {
|
|||||||
"Zugangsdaten des neue Hostsharing Pakets " + pacName,
|
"Zugangsdaten des neue Hostsharing Pakets " + pacName,
|
||||||
template.out())
|
template.out())
|
||||||
);
|
);
|
||||||
return new CompoundProcessor(hostsAppender, interfacesAppender, sudoersAppender, newUsersProc, emailPasswordProc);
|
Processor priProcessor = new CompoundProcessor(hostsAppender, interfacesAppender, sudoersAppender, newUsersProc);
|
||||||
|
WaitingTasksProcessor secProcessor = new WaitingTasksProcessor(priProcessor);
|
||||||
|
secProcessor.appendProcessor(pac.getHiveName(), emailPasswordProc, "send email to customer");
|
||||||
|
return secProcessor;
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
throw new ProcessorException(e);
|
throw new ProcessorException(e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
<!-- BEGIN: main -->Das neue Hostsharing Paket {PAC} ist eingerichtet. Zugangsdaten:
|
<!-- BEGIN: main -->Das neue Hostsharing Paket {PAC} ist eingerichtet.
|
||||||
|
Die Zugangsdaten sind:
|
||||||
|
|
||||||
Hostname (HTTP, FTP, SSH, POP3, IMAP): {PAC}.hostsharing.net
|
Hostname (HTTP, FTP, SSH, POP3, IMAP): {PAC}.hostsharing.net
|
||||||
Benutzernamen (Paket-Admin-Account): {PAC}
|
Benutzernamen (Paket-Admin-Account): {PAC}
|
||||||
Passwort: {PASSWORD}
|
Passwort: {PASSWORD}
|
||||||
|
|
||||||
Wir bitten zu berücksichtigen, dass man mit diesem Passwort sehr viel
|
Wir bitten zu beruecksichtigen, dass man mit diesem Passwort sehr viel
|
||||||
Macht über das Paket hat, so ist damit z.B. die Bestellung von Domains
|
Macht ueber das Paket hat. Bitte daher die u.g. Sicherheitshinweise
|
||||||
möglich. Bitte daher die u.g. Sicherheitshinweise beachten und den
|
beachten und den Paketadmin-Account {PAC} nicht mit unsicheren
|
||||||
Paketadmin-Account {PAC} nicht mit unsicheren (unverschlüsselten)
|
(unverschluesselten) Protokollen wie POP3 oder FTP ohne TLS verwenden!
|
||||||
Protokollen wie POP3 oder FTP ohne TLS verwenden!
|
|
||||||
|
|
||||||
E-Mail-Benachrichtigungen für den Paket-Admin gehen direkt an den
|
E-Mail-Benachrichtigungen fuer den Paket-Admin gehen direkt an den
|
||||||
o.g. Account. Über den E-Mail-Alias {PAC} können diese E-Mails
|
o.g. Account. Ueber den E-Mail-Alias {PAC} koennen diese E-Mails
|
||||||
an externe E-Mail-Adressen weitergeleitet werden. Initial ist
|
an externe E-Mail-Adressen weitergeleitet werden. Initial ist
|
||||||
eine Weiterleitung an {CUST_EMAIL} eingetragen.
|
eine Weiterleitung an {CUST_EMAIL} eingetragen.
|
||||||
|
|
||||||
@ -20,42 +20,43 @@ unter einem User "{PAC}-doms" anzulegen, um die Paket- und Domain-
|
|||||||
Verwaltung zu trennen. Dies gilt insbesondere, wenn die Domain-Inhalte
|
Verwaltung zu trennen. Dies gilt insbesondere, wenn die Domain-Inhalte
|
||||||
per FTP gepflegt werden sollen.
|
per FTP gepflegt werden sollen.
|
||||||
|
|
||||||
Weitere Accounts (neben dem Paketadmin-Account {PAC}) können nach einem
|
Weitere Accounts (neben dem Paketadmin-Account {PAC}) koennen nach einem
|
||||||
Login per SSH mit dem Kommandozeilen-Programm hsadmin eingerichtet
|
Login per SSH mit dem Kommandozeilen-Programm hsadmin eingerichtet
|
||||||
werden (in Kürze auch per Web-Client). Dokumentation finden Sie unter:
|
oder mit dem Web-Client unter http://admin.hostsharing.net
|
||||||
|
Dokumentation finden Sie unter:
|
||||||
|
|
||||||
<http://www.hostsharing.net/dokumentation.html>
|
<http://www.hostsharing.net/dokumentation.html>
|
||||||
|
|
||||||
Der Webspace des Paketes ist theoretisch ab sofort unter
|
Der Webspace des Paketes ist theoretisch ab sofort unter
|
||||||
<http://{PAC}.hostsharing.net/> erreichbar, allerdings kann es durch
|
<http://{PAC}.hostsharing.net/> erreichbar, allerdings kann es durch
|
||||||
DNS-Caches Verzögerungen geben. Das DocumentRoot ist ~{PAC}/web, wobei
|
DNS-Caches Verzoegerungen geben. Das DocumentRoot ist ~{PAC}/web, wobei
|
||||||
~{PAC}/cgi als /cgi-bin in den Webspace eingeblendet wird. In SW Paketen
|
~{PAC}/cgi als /cgi-bin in den Webspace eingeblendet wird. In SW Paketen
|
||||||
darf dieses CGI auch nur für administrative Zwecke verwendet werden.
|
darf dieses CGI nur fuer administrative Zwecke verwendet werden.
|
||||||
|
|
||||||
Die vorgenannte Paket-Subdomain ist jedoch eher zum Testen und Ausprobieren
|
Die vorgenannte Paket-Subdomain ist jedoch eher zum Testen und Ausprobieren
|
||||||
gedacht und hat mit dem folgenden Domain-Webspace nichts zu tun, der wird
|
gedacht und hat mit dem folgenden Domain-Webspace nichts zu tun, der wird
|
||||||
unter ~{PAC}/doms/ angelegt, sobald eine Domain aufgeschaltet wird. Dort gibt
|
unter ~{PAC}/doms/ angelegt, sobald eine Domain aufgeschaltet wird. Dort gibt
|
||||||
es dann für jede Domain ein separates Verzeichnis.
|
es dann fuer jede Domain ein separates Verzeichnis.
|
||||||
|
|
||||||
Das Verfahren zum Bestellen von Domains ist auf unserer Website unter
|
Das Verfahren zum Bestellen von Domains ist auf unserer Website unter
|
||||||
http://www.hostsharing.net/dokumentation/einstieg-bei-hostsharing/domain-bestellen.html
|
http://www.hostsharing.net/dokumentation/einstieg-bei-hostsharing/domain-bestellen.html
|
||||||
beschrieben. Ein Web-Interface hierfür ist in Entwicklung.
|
beschrieben.
|
||||||
|
|
||||||
Bei evtl. auftretenden Problemen mit dem Server bitte zunächst auf
|
Bei evtl. auftretenden Problemen mit dem Server bitte zunaechst auf
|
||||||
unserer Status-Website <http://status.hostsharing.net/> nachsehen,
|
unserer Status-Website <http://status.hostsharing.net/> nachsehen,
|
||||||
insbesondere auch auf der dortigen Seite "Aktionen", ob die Hostmaster
|
insbesondere auch auf der dortigen Seite "Aktionen", ob die Hostmaster
|
||||||
bereits aktiv sind. Falls nicht, können die Hostmaster bei dringenden
|
bereits aktiv sind. Falls nicht, koennen die Hostmaster bei dringenden
|
||||||
Problemen über die Rufnummer +49 40 209331331 erreicht werden.
|
Problemen ueber die Rufnummer +49 40 209331331 erreicht werden.
|
||||||
Bitte ggf. lange klingeln lassen, aber nicht mehr anrufen,
|
Bitte ggf. lange klingeln lassen, aber nicht mehr anrufen,
|
||||||
wenn die Hostmaster laut Status-Seite "Aktionen" bereits dabei sind,
|
wenn die Hostmaster laut Status-Seite "Aktionen" bereits dabei sind,
|
||||||
das Problem zu beheben, da dies die Arbeiten dann nur verzögern würde.
|
das Problem zu beheben, da dies die Arbeiten dann nur verzoegern wuerde.
|
||||||
Auch ist diese Rufnummer keine Support-Rufnummer, telefonische
|
Auch ist diese Rufnummer keine Support-Rufnummer, telefonische
|
||||||
Support-Anfragen können grundsätzlich nicht beantwortet werden.
|
Support-Anfragen koennen grundsaetzlich nicht beantwortet werden.
|
||||||
|
|
||||||
Weitere Fragen beantworten wir gerne per E-Mail, am liebsten auf der
|
Weitere Fragen beantworten wir gerne per E-Mail, am liebsten auf der
|
||||||
passenden öffentlichen Mailingliste (in den meisten Fällen wohl
|
passenden oeffentlichen Mailingliste (in den meisten Faellen wohl
|
||||||
support@). Einen Übeblick über unsere Mailinglisten bietet die Website:
|
support@). Einen Ueberblick ueber unsere Mailinglisten bietet die Website:
|
||||||
http://www.hostsharing.net/forum/mailinglisten.html
|
https://www.hostsharing.net/gemeinschaft
|
||||||
|
|
||||||
Viel Erfolg mit dem neuen Paket bei Hostsharing!
|
Viel Erfolg mit dem neuen Paket bei Hostsharing!
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ formuliert.
|
|||||||
--
|
--
|
||||||
Hostsharing Service | http://www.hostsharing.net
|
Hostsharing Service | http://www.hostsharing.net
|
||||||
Telefon: +49 40 209331311 | Fax: +49 40 209331312
|
Telefon: +49 40 209331311 | Fax: +49 40 209331312
|
||||||
Hostsharing eG | Glockengießerwall 17 | D-20095 Hamburg
|
Hostsharing eG | Glockengiesserwall 17 | D-20095 Hamburg
|
||||||
Registergericht Hamburg, GnR 1007 | USt.-ID-Nr.: DE218602793
|
Registergericht Hamburg, GnR 1007 | USt.-ID-Nr.: DE218602793
|
||||||
vertretungsberechtigter Vorstand: Michael Hierweck, Uwe Müller
|
vertretungsberechtigter Vorstand: Michael Hierweck, Uwe Mueller
|
||||||
<!-- END: main -->
|
<!-- END: main -->
|
14
hsarback/src/de/hsadmin/mods/pac/hosts.jtpl
Normal file
14
hsarback/src/de/hsadmin/mods/pac/hosts.jtpl
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!-- BEGIN: main -->127.0.0.1 localhost
|
||||||
|
|
||||||
|
::1 ip6-localhost ip6-loopback
|
||||||
|
fe00::0 ip6-localnet
|
||||||
|
ff00::0 ip6-mcastprefix
|
||||||
|
ff02::1 ip6-allnodes
|
||||||
|
ff02::2 ip6-allrouters
|
||||||
|
ff02::3 ip6-allhosts
|
||||||
|
|
||||||
|
{HIVE_IP} {HIVE}.hostsharing.net {HIVE} localhive
|
||||||
|
|
||||||
|
<!-- BEGIN: iterate -->{PAC_IP} {PAC}.hostsharing.net {PAC}
|
||||||
|
<!-- END: iterate -->
|
||||||
|
<!-- END: main -->
|
17
hsarback/src/de/hsadmin/mods/pac/interfaces.jtpl
Normal file
17
hsarback/src/de/hsadmin/mods/pac/interfaces.jtpl
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<!-- BEGIN: main -->auto lo
|
||||||
|
iface lo inet loopback
|
||||||
|
|
||||||
|
auto eth0
|
||||||
|
iface eth0 inet static
|
||||||
|
address {HIVE_IP}
|
||||||
|
netmask 255.255.255.0
|
||||||
|
gateway {HIVE_GATEWAY}
|
||||||
|
|
||||||
|
<!-- BEGIN: iterate -->auto eth0:{PAC}
|
||||||
|
iface eth0:{PAC} inet static
|
||||||
|
address {PAC_IP}
|
||||||
|
netmask 255.255.255.0
|
||||||
|
|
||||||
|
<!-- END: iterate -->
|
||||||
|
<!-- END: main -->
|
||||||
|
|
25
hsarback/src/de/hsadmin/mods/pac/sudoers.jtpl
Normal file
25
hsarback/src/de/hsadmin/mods/pac/sudoers.jtpl
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!-- BEGIN: main -->### Do not edit this file manually
|
||||||
|
### Generated by HSAdmin Queue Server
|
||||||
|
|
||||||
|
# Host alias specification
|
||||||
|
|
||||||
|
# User alias specification
|
||||||
|
|
||||||
|
# Cmnd alias specification
|
||||||
|
|
||||||
|
# Override built in defaults
|
||||||
|
|
||||||
|
Defaults ignore_dot # "." bzw. "" im PATH ignorieren
|
||||||
|
Defaults always_set_home # HOME entsprechend des Zielusers aendern
|
||||||
|
Defaults env_reset # Environmentvariablen filtern
|
||||||
|
Defaults listpw=all # siehe sudoers(5)
|
||||||
|
|
||||||
|
# User privilege specification
|
||||||
|
root ALL=(ALL) ALL
|
||||||
|
%adm ALL=NOPASSWD: ALL
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
<!-- BEGIN: iterate -->{PAC} ALL = (%{PAC}) NOPASSWD: ALL
|
||||||
|
<!-- END: iterate -->
|
||||||
|
<!-- END: main -->
|
Loading…
Reference in New Issue
Block a user