main.go 4.44 KB
Newer Older
1
2
3
package main

import (
4
	"encoding/json"
5
6
7
	"fmt"
	"os"

8
	"github.com/Sirupsen/logrus"
9
	"github.com/go-errors/errors"
Sietse Ringers's avatar
Sietse Ringers committed
10
11
	"github.com/privacybydesign/irmago/server"
	"github.com/privacybydesign/irmago/server/irmaserver"
12
13
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
14
15
)

16
17
var conf *irmaserver.Configuration

18
func main() {
19
20
21
22
23
24
25
26
27
28
29
30
	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))
			}
		},
	}
31

32
33
	if err := setFlags(cmd); err != nil {
		die(errors.WrapPrefix(err, "Failed to attach flags", 0))
34
35
	}

36
37
	if err := cmd.Execute(); err != nil {
		die(errors.WrapPrefix(err, "Failed to execute command", 0))
38
	}
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
}

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("requestors", "", "Requestor configuration (in JSON)")

60
61
62
63
64
65
66
	flags.StringSlice("disclosing", nil, "Comma-separated list of attributes that all requestors may verify")
	flags.StringSlice("signing", nil, "Comma-separated list of attributes that all requestors may request in signatures")
	flags.StringSlice("issuing", nil, "Comma-separated list of attributes that all requestors may issue")
	flags.Lookup("disclosing").NoOptDefVal = "*"
	flags.Lookup("signing").NoOptDefVal = "*"
	flags.Lookup("issuing").NoOptDefVal = "*"

67
68
69
70
71
72
73
74
75
	return viper.BindPFlags(flags)
}

func configure() error {
	fmt.Println("Configuring")

	// Environment variables
	viper.SetEnvPrefix("IRMASERVER")
	viper.AutomaticEnv()
76

77
78
79
80
81
82
83
84
85
86
87
88
89
	// 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{
Sietse Ringers's avatar
Sietse Ringers committed
90
		Configuration: &server.Configuration{
91
92
93
			IrmaConfigurationPath: viper.GetString("irmaconf"),
			IssuerPrivateKeysPath: viper.GetString("privatekeys"),
			Logger:                logrus.StandardLogger(),
94
		},
95
96
97
98
99
100
101
102
		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"),
	}

103
104
	// Handle global permissions
	if len(viper.GetStringMap("permissions")) > 0 { // First read config file
105
106
107
108
		if err := viper.UnmarshalKey("permissions", &conf.GlobalPermissions); err != nil {
			return errors.WrapPrefix(err, "Failed to unmarshal permissions", 0)
		}
	}
109
110
111
112
113
114
115
116
117
118
119
	handlePermission(&conf.GlobalPermissions.Disclosing, "disclosing") // Read flag or env var
	handlePermission(&conf.GlobalPermissions.Signing, "signing")
	handlePermission(&conf.GlobalPermissions.Issuing, "issuing")

	// Handle requestors
	if len(viper.GetStringMap("requestors")) > 0 { // First read config file
		if err := viper.UnmarshalKey("requestors", &conf.Requestors); err != nil {
			return errors.WrapPrefix(err, "Failed to unmarshal requestors", 0)
		}
	}
	requestors := viper.GetString("requestors") // Read flag or env var
120
121
122
123
124
125
126
127
128
129
130
	if len(requestors) > 0 {
		if err := json.Unmarshal([]byte(requestors), &conf.Requestors); err != nil {
			return errors.WrapPrefix(err, "Failed to parse requestors", 0)
		}
	}

	bts, _ := json.MarshalIndent(conf, "", "   ")
	fmt.Println(string(bts))
	fmt.Println("Done configuring")

	return nil
131
}
132
133
134
135
136
137
138
139
140
141

func handlePermission(conf *[]string, typ string) {
	if viper.GetString(typ) == "*" {
		*conf = []string{"*"}
	}
	perms := viper.GetStringSlice(typ)
	if len(perms) > 0 {
		*conf = perms
	}
}