Commit 8c63cec3 authored by Sietse Ringers's avatar Sietse Ringers
Browse files

Make server configurable using flags, env vars, and config file


Co-authored-by: Tomas's avatarConfiks <confiks@scriptbase.org>
parent 4df6271b
......@@ -55,3 +55,7 @@
[prune]
go-tests = true
unused-packages = true
[[constraint]]
name = "github.com/spf13/viper"
version = "1.3.1"
......@@ -40,6 +40,7 @@ var IrmaServerConfiguration = &irmaserver.Configuration{
IrmaConfigurationPath: filepath.Join(testdata, "irma_configuration"),
IssuerPrivateKeysPath: filepath.Join(testdata, "privatekeys"),
},
DisableRequestorAuthentication: true,
Port: 48682,
}
......@@ -50,7 +51,7 @@ var JwtServerConfiguration = &irmaserver.Configuration{
IssuerPrivateKeysPath: filepath.Join(testdata, "privatekeys"),
},
Port: 48682,
AuthenticateRequestors: true,
DisableRequestorAuthentication: false,
GlobalPermissions: irmaserver.Permissions{
Disclosing: []string{"*"},
Signing: []string{"*"},
......
......@@ -14,13 +14,11 @@ import (
var Logger *logrus.Logger = logrus.StandardLogger()
type Configuration struct {
IrmaConfigurationPath string
IssuerPrivateKeysPath string
Logger *logrus.Logger `json:"-"`
IssuerPrivateKeys map[irma.IssuerIdentifier]*gabi.PrivateKey `json:"-"`
IrmaConfiguration *irma.Configuration `json:"-"`
IrmaConfigurationPath string `json:"irmaconf" mapstructure:"irmaconf"`
IssuerPrivateKeysPath string `json:"privatekeys" mapstructure:"privatekeys"`
Logger *logrus.Logger `json:"-"`
IssuerPrivateKeys map[irma.IssuerIdentifier]*gabi.PrivateKey `json:"-"`
IrmaConfiguration *irma.Configuration `json:"-"`
}
type SessionResult struct {
......
package main
import (
"encoding/json"
"fmt"
"os"
"strconv"
"github.com/Sirupsen/logrus"
"github.com/go-errors/errors"
"github.com/privacybydesign/irmago/server"
"github.com/privacybydesign/irmago/server/irmaserver"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var conf *irmaserver.Configuration
func main() {
var err error
defer func() {
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
os.Exit(0)
}()
var cmd = &cobra.Command{
Use: "irmaserver",
Short: "IRMA server for verifying and issuing attributes",
Run: func(command *cobra.Command, args []string) {
if err := configure(); err != nil {
die(errors.WrapPrefix(err, "Failed to configure server", 0))
}
if err := irmaserver.Start(conf); err != nil {
die(errors.WrapPrefix(err, "Failed to start server", 0))
}
},
}
if len(os.Args) != 3 {
err = errors.New("Usage: irmaserver port path")
return
if err := setFlags(cmd); err != nil {
die(errors.WrapPrefix(err, "Failed to attach flags", 0))
}
port, err := strconv.Atoi(os.Args[1])
if err != nil {
err = errors.New("First argument must be an integer")
return
if err := cmd.Execute(); err != nil {
die(errors.WrapPrefix(err, "Failed to execute command", 0))
}
}
func die(err *errors.Error) {
fmt.Println(err.Error())
fmt.Println()
fmt.Println(string(err.Stack()))
os.Exit(1)
}
func setFlags(cmd *cobra.Command) error {
flags := cmd.Flags()
flags.SortFlags = false
flags.StringP("irmaconf", "i", "./irma_configuration", "path to irma_configuration")
flags.StringP("privatekeys", "k", "", "path to IRMA private keys")
flags.StringP("jwtissuer", "j", "irmaserver", "JWT issuer")
flags.StringP("jwtprivatekey", "w", "", "JWT private key or path to it")
flags.IntP("port", "p", 8088, "Port at which to listen")
flags.Bool("noauth", false, "Whether or not to authenticate requestors")
flags.String("permissions", "", "Default permissions")
flags.String("requestors", "", "Requestor configuration (in JSON)")
return viper.BindPFlags(flags)
}
func configure() error {
fmt.Println("Configuring")
// Environment variables
viper.SetEnvPrefix("IRMASERVER")
viper.AutomaticEnv()
err = irmaserver.Start(&irmaserver.Configuration{
// Configuration file
viper.SetConfigName("config")
viper.AddConfigPath(".")
viper.AddConfigPath("/etc/irmaserver/")
viper.AddConfigPath("$HOME/.irmaserver")
if err := viper.ReadInConfig(); err != nil {
fmt.Printf("No configuration file found")
} else {
fmt.Println("Config file: ", viper.ConfigFileUsed())
}
// Read configuration from flags and/or environmental variables
conf = &irmaserver.Configuration{
Configuration: &server.Configuration{
IrmaConfigurationPath: os.Args[2],
IrmaConfigurationPath: viper.GetString("irmaconf"),
IssuerPrivateKeysPath: viper.GetString("privatekeys"),
Logger: logrus.StandardLogger(),
},
Port: port,
})
Port: viper.GetInt("port"),
DisableRequestorAuthentication: viper.GetBool("noauth"),
Requestors: make(map[string]irmaserver.Requestor),
GlobalPermissions: irmaserver.Permissions{},
JwtIssuer: viper.GetString("jwtissuer"),
JwtPrivateKey: viper.GetString("jwtprivatekey"),
}
// Handle special permissions
permissions := viper.GetString("permissions")
if len(permissions) > 0 {
if err := json.Unmarshal([]byte(permissions), &conf.GlobalPermissions); err != nil {
return errors.WrapPrefix(err, "Failed to parse permissions", 0)
}
} else if len(viper.GetStringMap("permissions")) > 0 {
if err := viper.UnmarshalKey("permissions", &conf.GlobalPermissions); err != nil {
return errors.WrapPrefix(err, "Failed to unmarshal permissions", 0)
}
}
requestors := viper.GetString("requestors")
if len(requestors) > 0 {
if err := json.Unmarshal([]byte(requestors), &conf.Requestors); err != nil {
return errors.WrapPrefix(err, "Failed to parse requestors", 0)
}
} else if len(viper.GetStringMap("requestors")) > 0 {
if err := viper.UnmarshalKey("requestors", &conf.Requestors); err != nil {
return errors.WrapPrefix(err, "Failed to unmarshal requestors", 0)
}
}
bts, _ := json.MarshalIndent(conf, "", " ")
fmt.Println(string(bts))
fmt.Println("Done configuring")
return nil
}
......@@ -13,37 +13,42 @@ import (
)
type Configuration struct {
*server.Configuration
Port int
*server.Configuration `mapstructure:",squash"`
// Whether or not incoming session requests should be authenticated. If false, anyone
// can submit session requests. If true, the request is first authenticated against the
// server configuration before the server accepts it.
AuthenticateRequestors bool
Requestors map[string]Requestor // Requestor-specific permission and authentication configuration
GlobalPermissions Permissions // Disclosing, signing or issuance permissions that apply to all requestors
JwtIssuer string // Used in the "iss" field of result JWTs from /result-jwt and /getproof
JwtPrivateKey string // Private key to sign result JWTs with. If absent, /result-jwt and /getproof are disabled.
DisableRequestorAuthentication bool `json:"noauth" mapstructure:"noauth"`
// Port to listen at
Port int `json:"port" mapstructure:"port"`
// Requestor-specific permission and authentication configuration
RequestorsString string `json:"-" mapstructure:"requestors"`
Requestors map[string]Requestor `json:"requestors"`
// Disclosing, signing or issuance permissions that apply to all requestors
GlobalPermissionsString string `json:"-" mapstructure:"permissions"`
GlobalPermissions Permissions `json:"permissions"`
// Used in the "iss" field of result JWTs from /result-jwt and /getproof
JwtIssuer string `json:"jwtissuer" mapstructure:"jwtissuer"`
// Private key to sign result JWTs with. If absent, /result-jwt and /getproof are disabled.
JwtPrivateKey string `json:"jwtprivatekey" mapstructure:"jwtprivatekey"`
jwtPrivateKey *rsa.PrivateKey
}
// Permissions specify which attributes or credential a requestor may verify or issue.
type Permissions struct {
Disclosing []string
Signing []string
Issuing []string
Disclosing []string `json:"disclosing" mapstructure:"disclosing"`
Signing []string `json:"signing" mapstructure:"signing"`
Issuing []string `json:"issuing" mapstructure:"issuing"`
}
// Requestor contains all configuration (disclosure or verification permissions and authentication)
// for a requestor.
type Requestor struct {
Permissions
Permissions `mapstructure:",squash"`
AuthenticationMethod AuthenticationMethod
AuthenticationKey string
AuthenticationMethod AuthenticationMethod `json:"authmethod" mapstructure:"authmethod"`
AuthenticationKey string `json:"key" mapstructure:"key"`
}
// CanIssue returns whether or not the specified requestor may issue the specified credentials.
......@@ -109,7 +114,7 @@ func (conf *Configuration) initialize() error {
return err
}
if !conf.AuthenticateRequestors {
if conf.DisableRequestorAuthentication {
conf.Logger.Warn("Authentication of incoming session requests disabled")
authenticators = map[AuthenticationMethod]Authenticator{AuthenticationMethodNone: NilAuthenticator{}}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment