Creating nginx configurations for Domino SSL
Websites need to be secure, so the SHA-1 cipher is coming to an end. Despite best efforts, Domino is stuck with this outdated Cipher. While you can, on Windows, hide Domino behind IHS, I find nginx easier to tame.
Jesse explains how to configure nginx as the Domino proxy. So all is good, expecially since he also covered High availability.
But when you have a lot of sites, that's a lot of typing (and copy & paste from the Internet site documents). Mustache to the rescue! I've written about Mustache before and it suits the task quite nicely:
The Java code takes in the file name of that template as parameter, so when you feel you rather use Apache or need a different output (e.g. a report), you are free to supply a different file here.The Java is quite simple and should be self explanatory. Since it is a one-time, you-know-what-you-are-doing utility, there is no real error handling:
As usual YMMV.
Jesse explains how to configure nginx as the Domino proxy. So all is good, expecially since he also covered High availability.
But when you have a lot of sites, that's a lot of typing (and copy & paste from the Internet site documents). Mustache to the rescue! I've written about Mustache before and it suits the task quite nicely:
- Create one well working sample configuration
- Replace the site specific values with {{mustache}} variables
- Run it against all Internet site documents
{{name}}
The name of the site according to the configuration document. I use it here to configure the file name{{siteName}}
The first web name, it will become the listen parameter{{allNames}}
All web names, they will be listed asserver_name
{{settings}}
all field values of the Internet site documents as concatenated strings. Using a dot notation they can be used directly. e.g.{{settings.SSLKeyFile}}
. Using this approach you can do whatever is needed to generate your desired output
server {
listen {{siteName}}:443;
server_name {{#allNames}} {{.}}{{/allNames}};
client_max_body_size 100m;
ssl on;
# Original keyfile: {{settings.SSLKeyFile}}
ssl_certificate /etc/nginx/ssl/{{name}}.pem;
ssl_certificate_key /etc/nginx/ssl/{{name}}.key;
location / {
proxy_read_timeout 240;
proxy_pass http://localhost:8088;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header $WSRA $remote_addr;
proxy_set_header $WSRH $remote_addr;
proxy_set_header $WSSN $host;
proxy_set_header $WSIS True;
}
}
The Java code takes in the file name of that template as parameter, so when you feel you rather use Apache or need a different output (e.g. a report), you are free to supply a different file here.The Java is quite simple and should be self explanatory. Since it is a one-time, you-know-what-you-are-doing utility, there is no real error handling:
package com.notessensei.nginxdomino;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.NotesException;
import lotus.domino.NotesFactory;
import lotus.domino.NotesThread;
import lotus.domino.Session;
import lotus.domino.View;
import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheFactory;
public class ConfigGenerator {
private static final String VIEW_NAME = "($InternetSites)";
private static final String WEB_FORM = "WebSite";
private final File outDir;
private final String dirFileName;
private final String templateFileName;
public ConfigGenerator(String outputDir, String fileName, String templateFile) {
this.outDir = new File(outputDir);
this.dirFileName = fileName;
this.templateFileName = templateFile;
if (!outDir.exists()) {
outDir.mkdirs();
}
}
public static void main(String[] args) {
if (args.length < 3) {
System.err.println("Usage java -jar ngixdomino [outputdir] [path-to-local-pubnames] [path-to-template]");
System.exit(1);
}
ConfigGenerator cg = new ConfigGenerator(args[0], args[1], args[2]);
cg.generateDefaultConfigs();
System.out.println("Done ..");
}
public void generateDefaultConfigs() {
// Here we read from domino
final Collection<InternetSite> internetSites = new ArrayList<InternetSite>();
this.populateInternetSites(internetSites);
if (internetSites.size() == 0) {
System.err.println("Something went wrong, got no internet sites!");
System.exit(2);
}
Mustache mustache = this.getDefaultTemplate();
this.renderConfigs(mustache, internetSites);
}
private void renderConfigs(Mustache mustache, Collection<InternetSite> internetSites) {
for (InternetSite is : internetSites) {
String outfileName = this.outDir.getPath() + File.separator + is.getName();
System.out.println("Creating " + outfileName);
try {
FileOutputStream out = new FileOutputStream(new File(outfileName));
Writer pw = new PrintWriter(out);
mustache.execute(pw, is);
pw.flush();
pw.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private Mustache getDefaultTemplate() {
MustacheFactory mf = new DefaultMustacheFactory();
return mf.compile(this.templateFileName);
}
private void populateInternetSites(Collection<InternetSite> internetSites) {
Session s = null;
Database nab = null;
View v = null;
Document doc = null;
NotesThread.sinitThread();
try {
s = NotesFactory.createSession();
nab = s.getDatabase("", this.dirFileName);
v = nab.getView(VIEW_NAME);
doc = v.getFirstDocument();
while (doc != null) {
Document nextDoc = v.getNextDocument(doc);
this.addoneInternetSite(internetSites, doc);
doc.recycle();
doc = nextDoc;
}
Utils.shred(doc, v, nab);
} catch (NotesException e) {
e.printStackTrace();
}
NotesThread.stermThread();
}
private void addoneInternetSite(Collection<InternetSite> internetSites, Document doc) throws NotesException {
// Is it an internet site?
if (!doc.getItemValueString("Form").equals(WEB_FORM)) {
return; // Not an internet site
}
InternetSite is = new InternetSite(doc);
internetSites.add(is);
}
}
package com.notessensei.nginxdomino;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import lotus.domino.Document;
import lotus.domino.Item;
import lotus.domino.NotesException;
public class InternetSite {
private static final String SITE_NAME_ITEM = "ISiteName";
private static final String ALL_NAMES_ITEM = "ISiteAdrs";
private final String name;
private final ArrayList<String> allNames = new ArrayList<String>();
private final Map<String, String> settings = new HashMap<String, String>();
public InternetSite(Document doc) throws NotesException {
this.name = doc.getItemValueString(SITE_NAME_ITEM);
@SuppressWarnings("rawtypes")
Vector v = doc.getItemValue(ALL_NAMES_ITEM);
for (Object o : v) {
this.allNames.add(o.toString());
}
for (Object o : doc.getItems()) {
if (o instanceof Item) {
Item i = (Item) o;
this.settings.put(i.getName(), i.getValueString());
}
}
}
public String getName() {
return this.name;
}
public String getSiteName() {
return this.allNames.get(0);
}
public Collection<String> getAllNames() {
return this.allNames;
}
public Map<String,String> getSettings() {
return this.settings;
}
}
As usual YMMV.
Posted by Stephan H Wissel on 20 September 2014 | Comments (1) | categories: IBM Notes nginx