mirror of https://github.com/perkeep/perkeep.git
auth: config for a non dev mode,
self gen tls certs, force https in non dev Change-Id: I7faa6b35f44a7925b06d22ade7f5986a12728362
This commit is contained in:
parent
edf4da987e
commit
e233c981e0
|
@ -1,6 +1,7 @@
|
||||||
{ "_for-emacs": "-*- mode: js2;-*-",
|
{ "_for-emacs": "-*- mode: js2;-*-",
|
||||||
"baseURL": ["_env", "${CAMLI_BASEURL}"],
|
"baseURL": ["_env", "${CAMLI_BASEURL}"],
|
||||||
"password": ["_env", "${CAMLI_PASSWORD}"],
|
"password": ["_env", "${CAMLI_PASSWORD}"],
|
||||||
|
"httpsOnly": false,
|
||||||
"prefixes": {
|
"prefixes": {
|
||||||
"/": {
|
"/": {
|
||||||
"handler": "root",
|
"handler": "root",
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
{ "_for-emacs": "-*- mode: js2;-*-",
|
||||||
|
"baseURL": ["_env", "${CAMLI_BASEURL}"],
|
||||||
|
"password": ["_env", "${CAMLI_PASSWORD}"],
|
||||||
|
"httpsOnly": true,
|
||||||
|
"TLSCertFile": "config/selfgen_cert.pem",
|
||||||
|
"TLSKeyFile": "config/selfgen_key.pem",
|
||||||
|
"prefixes": {
|
||||||
|
"/": {
|
||||||
|
"handler": "root",
|
||||||
|
"handlerArgs": {
|
||||||
|
"stealth": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/blog/": {
|
||||||
|
"handler": "publish",
|
||||||
|
"handlerArgs": {
|
||||||
|
"rootName": "dev-blog-root",
|
||||||
|
"blobRoot": "/bs/",
|
||||||
|
"searchRoot": "/my-search/",
|
||||||
|
"cache": "/cache/",
|
||||||
|
"devBootstrapPermanodeUsing": "/sighelper/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/pics/": {
|
||||||
|
"handler": "publish",
|
||||||
|
"handlerArgs": {
|
||||||
|
"rootName": "dev-pics-root",
|
||||||
|
"blobRoot": "/bs/",
|
||||||
|
"searchRoot": "/my-search/",
|
||||||
|
"cache": "/cache/",
|
||||||
|
"scaledImage": "lrucache",
|
||||||
|
"css": ["pics.css"],
|
||||||
|
"js": ["camli.js", "pics.js"],
|
||||||
|
"devBootstrapPermanodeUsing": "/sighelper/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/stub-test-disable/": {
|
||||||
|
"handler": "publish",
|
||||||
|
"enabled": false,
|
||||||
|
"handlerArgs": {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/ui/": {
|
||||||
|
"handler": "ui",
|
||||||
|
"handlerArgs": {
|
||||||
|
"blobRoot": "/bs-and-maybe-also-index/",
|
||||||
|
"searchRoot": "/my-search/",
|
||||||
|
"jsonSignRoot": "/sighelper/",
|
||||||
|
"cache": "/cache/",
|
||||||
|
"scaledImage": "lrucache",
|
||||||
|
"publishRoots": ["/blog/", "/pics/"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/sync/": {
|
||||||
|
"handler": "sync",
|
||||||
|
"handlerArgs": {
|
||||||
|
"from": "/bs/",
|
||||||
|
"to": "/indexer/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/sighelper/": {
|
||||||
|
"handler": "jsonsign",
|
||||||
|
"handlerArgs": {
|
||||||
|
"secretRing": ["_env", "${CAMLI_SECRET_RING}"],
|
||||||
|
"keyId": "26F5ABDA",
|
||||||
|
"publicKeyDest": "/bs/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/bs-and-index/": {
|
||||||
|
"handler": "storage-replica",
|
||||||
|
"handlerArgs": {
|
||||||
|
"backends": ["/bs/", "/indexer/"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/bs-and-maybe-also-index/": {
|
||||||
|
"handler": "storage-cond",
|
||||||
|
"handlerArgs": {
|
||||||
|
"write": {
|
||||||
|
"if": "isSchema",
|
||||||
|
"then": "/bs-and-index/",
|
||||||
|
"else": "/bs/"
|
||||||
|
},
|
||||||
|
"read": "/bs/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/bs/": {
|
||||||
|
"handler": "storage-filesystem",
|
||||||
|
"handlerArgs": {
|
||||||
|
"path": ["_env", "${CAMLI_ROOT}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/cache/": {
|
||||||
|
"handler": "storage-filesystem",
|
||||||
|
"handlerArgs": {
|
||||||
|
"path": ["_env", "${CAMLI_ROOT_CACHE}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/sharder/": {
|
||||||
|
"handler": "storage-shard",
|
||||||
|
"handlerArgs": {
|
||||||
|
"backends": ["/s1/", "/s2/"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/s1/": {
|
||||||
|
"handler": "storage-filesystem",
|
||||||
|
"handlerArgs": {
|
||||||
|
"path": ["_env", "${CAMLI_ROOT_SHARD1}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/s2/": {
|
||||||
|
"handler": "storage-filesystem",
|
||||||
|
"handlerArgs": {
|
||||||
|
"path": ["_env", "${CAMLI_ROOT_SHARD2}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/repl/": {
|
||||||
|
"handler": "storage-replica",
|
||||||
|
"handlerArgs": {
|
||||||
|
"backends": ["/r1/", "/r2/", "/r3/"],
|
||||||
|
"minWritesForSuccess": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/r1/": {
|
||||||
|
"handler": "storage-filesystem",
|
||||||
|
"handlerArgs": {
|
||||||
|
"path": ["_env", "${CAMLI_ROOT_REPLICA1}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/r2/": {
|
||||||
|
"handler": "storage-filesystem",
|
||||||
|
"handlerArgs": {
|
||||||
|
"path": ["_env", "${CAMLI_ROOT_REPLICA2}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/r3/": {
|
||||||
|
"handler": "storage-filesystem",
|
||||||
|
"handlerArgs": {
|
||||||
|
"path": ["_env", "${CAMLI_ROOT_REPLICA3}"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/indexer/": {
|
||||||
|
"handler": "storage-mysqlindexer",
|
||||||
|
"handlerArgs": {
|
||||||
|
"database": ["_env", "${CAMLI_DBNAME}"],
|
||||||
|
"user": "root",
|
||||||
|
"password": "root",
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"blobSource": "/bs/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"/my-search/": {
|
||||||
|
"handler": "search",
|
||||||
|
"handlerArgs": {
|
||||||
|
"index": "/indexer/",
|
||||||
|
"owner": "sha1-ad87ca5c78bd0ce1195c46f7c98e6025abbaf007"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,11 +17,18 @@ limitations under the License.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"big"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
@ -42,6 +49,9 @@ import (
|
||||||
_ "camli/server" // UI, publish, etc
|
_ "camli/server" // UI, publish, etc
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const defCert = "config/selfgen_cert.pem"
|
||||||
|
const defKey = "config/selfgen_key.pem"
|
||||||
|
|
||||||
var flagConfigFile = flag.String("configfile", "serverconfig",
|
var flagConfigFile = flag.String("configfile", "serverconfig",
|
||||||
"Config file to use, relative to camli config dir root, or blank to not use config files.")
|
"Config file to use, relative to camli config dir root, or blank to not use config files.")
|
||||||
|
|
||||||
|
@ -53,6 +63,60 @@ func exitFailure(pattern string, args ...interface{}) {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mostly copied from $GOROOT/src/pkg/crypto/tls/generate_cert.go
|
||||||
|
func genSelfTLS() os.Error {
|
||||||
|
priv, err := rsa.GenerateKey(rand.Reader, 1024)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to generate private key: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Seconds()
|
||||||
|
|
||||||
|
baseurl := os.Getenv("CAMLI_BASEURL")
|
||||||
|
if baseurl == "" {
|
||||||
|
return fmt.Errorf("CAMLI_BASEURL is not set")
|
||||||
|
}
|
||||||
|
split := strings.Split(baseurl, ":")
|
||||||
|
hostname := split[1]
|
||||||
|
hostname = hostname[2:len(hostname)]
|
||||||
|
println(hostname)
|
||||||
|
|
||||||
|
template := x509.Certificate{
|
||||||
|
SerialNumber: new(big.Int).SetInt64(0),
|
||||||
|
Subject: pkix.Name{
|
||||||
|
CommonName: hostname,
|
||||||
|
Organization: []string{hostname},
|
||||||
|
},
|
||||||
|
NotBefore: time.SecondsToUTC(now - 300),
|
||||||
|
NotAfter: time.SecondsToUTC(now + 60*60*24*365), // valid for 1 year.
|
||||||
|
|
||||||
|
SubjectKeyId: []byte{1, 2, 3, 4},
|
||||||
|
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||||
|
}
|
||||||
|
|
||||||
|
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to create certificate: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
certOut, err := os.Create(defCert)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open %s for writing: %s", defCert, err)
|
||||||
|
}
|
||||||
|
pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
||||||
|
certOut.Close()
|
||||||
|
log.Printf("written %s\n", defCert)
|
||||||
|
|
||||||
|
keyOut, err := os.OpenFile(defKey, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open %s for writing:", defKey, err)
|
||||||
|
}
|
||||||
|
pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
|
||||||
|
keyOut.Close()
|
||||||
|
log.Printf("written %s\n", defKey)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
@ -69,11 +133,21 @@ func main() {
|
||||||
baseURL := ws.BaseURL()
|
baseURL := ws.BaseURL()
|
||||||
|
|
||||||
{
|
{
|
||||||
cert, key := config.OptionalString("TLSCertFile", ""), config.OptionalString("TLSKeyFile", "")
|
secure := config.OptionalBool("httpsOnly", true)
|
||||||
if (cert != "") != (key != "") {
|
if secure {
|
||||||
exitFailure("TLSCertFile and TLSKeyFile must both be either present or absent")
|
cert, key := config.OptionalString("TLSCertFile", ""), config.OptionalString("TLSKeyFile", "")
|
||||||
}
|
if (cert != "") != (key != "") {
|
||||||
if cert != "" {
|
exitFailure("TLSCertFile and TLSKeyFile must both be either present or absent")
|
||||||
|
}
|
||||||
|
|
||||||
|
if cert == "" && key == "" {
|
||||||
|
err = genSelfTLS()
|
||||||
|
if err != nil {
|
||||||
|
exitFailure("pb generating the self signed creds: %q", err)
|
||||||
|
}
|
||||||
|
cert = defCert
|
||||||
|
key = defKey
|
||||||
|
}
|
||||||
ws.SetTLS(cert, key)
|
ws.SetTLS(cert, key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use FindBin qw($Bin);
|
||||||
|
use Getopt::Long;
|
||||||
|
|
||||||
|
sub usage {
|
||||||
|
die "Usage: server [--wipe] <portnumber> -- [other_blobserver_opts]";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $opt_wipe;
|
||||||
|
my $opt_nobuild;
|
||||||
|
my $opt_all; # listen on all interfaces
|
||||||
|
GetOptions("wipe" => \$opt_wipe,
|
||||||
|
"all" => \$opt_all,
|
||||||
|
"nobuild" => \$opt_nobuild,
|
||||||
|
)
|
||||||
|
or usage();
|
||||||
|
|
||||||
|
my $port = shift;
|
||||||
|
$port = "3179" unless defined($port);
|
||||||
|
usage() unless $port =~ /^\d+$/;
|
||||||
|
|
||||||
|
unless ($opt_nobuild) {
|
||||||
|
system("./build.pl", "server/go/camlistored") and die "Failed to build camlistored";
|
||||||
|
system("./build.pl", "clients/go/camdbinit") and die "Failed to build camdbinit";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $root = "/tmp/camliroot-$ENV{USER}/port$port/";
|
||||||
|
if ($opt_wipe && -d $root) {
|
||||||
|
print "Wiping $root\n";
|
||||||
|
system("rm", "-rf", $root) and die "Failed to wipe $root.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $suffixdir = sub {
|
||||||
|
my $suffix = shift;
|
||||||
|
my $root = "$root/$suffix";
|
||||||
|
unless (-d $root) {
|
||||||
|
system("mkdir", "-p", $root) and die "Failed to create $root.\n";
|
||||||
|
}
|
||||||
|
return $root;
|
||||||
|
};
|
||||||
|
|
||||||
|
my $DBNAME = "devcamli$ENV{USER}";
|
||||||
|
my @opts;
|
||||||
|
if ($opt_wipe) {
|
||||||
|
push @opts, "-wipe";
|
||||||
|
} else {
|
||||||
|
push @opts, "-ignoreexists";
|
||||||
|
}
|
||||||
|
|
||||||
|
system("./clients/go/camdbinit/camdbinit",
|
||||||
|
"-user=root",
|
||||||
|
"-password=root",
|
||||||
|
"-host=localhost",
|
||||||
|
"-database=$DBNAME",
|
||||||
|
@opts) and die "Failed to run camdbinit.\n";
|
||||||
|
|
||||||
|
my $base = "https://localhost:$port";
|
||||||
|
my $listen = "127.0.0.1:$port";
|
||||||
|
if ($opt_all) {
|
||||||
|
$listen = "0.0.0.0:$port";
|
||||||
|
my $host = `hostname`;
|
||||||
|
chomp $host;
|
||||||
|
$base = "https://$host:$port";
|
||||||
|
}
|
||||||
|
|
||||||
|
print "Starting dev server on $base/ui/ with password \"pass$port\"\n";
|
||||||
|
|
||||||
|
$ENV{CAMLI_BASEURL} = $base;
|
||||||
|
$ENV{CAMLI_PASSWORD} = "pass$port";
|
||||||
|
# do we simply set that one to empty in non dev, or do we deal with it in auth/auth.go ?
|
||||||
|
$ENV{CAMLI_ADVERTISED_PASSWORD} = ""; # public password
|
||||||
|
$ENV{CAMLI_ROOT} = $suffixdir->("bs");
|
||||||
|
$ENV{CAMLI_ROOT_SHARD1} = $suffixdir->("s1");
|
||||||
|
$ENV{CAMLI_ROOT_SHARD2} = $suffixdir->("s2");
|
||||||
|
$ENV{CAMLI_ROOT_REPLICA1} = $suffixdir->("r1");
|
||||||
|
$ENV{CAMLI_ROOT_REPLICA2} = $suffixdir->("r2");
|
||||||
|
$ENV{CAMLI_ROOT_REPLICA3} = $suffixdir->("r3");
|
||||||
|
$ENV{CAMLI_ROOT_CACHE} = $suffixdir->("cache");
|
||||||
|
$ENV{CAMLI_PORT} = $port;
|
||||||
|
$ENV{CAMLI_SECRET_RING} = "$Bin/lib/go/camli/jsonsign/testdata/test-secring.gpg";
|
||||||
|
$ENV{CAMLI_DBNAME} = $DBNAME;
|
||||||
|
|
||||||
|
# To use resources from disk, instead of the copies linked into the
|
||||||
|
# binary:
|
||||||
|
$ENV{CAMLI_DEV_UI_FILES} = "$FindBin::Bin/server/go/camlistored/ui"; # set in server/go/camlistored/ui/fileembed.go
|
||||||
|
|
||||||
|
exec("$FindBin::Bin/server/go/camlistored/camlistored",
|
||||||
|
"-configfile=$Bin/config/server-config.json",
|
||||||
|
"-listen=$listen",
|
||||||
|
@ARGV);
|
Loading…
Reference in New Issue