keyshare-server.go 5.87 KB
Newer Older
1
2
3
package cmd

import (
4
	"github.com/go-errors/errors"
5
	irma "github.com/privacybydesign/irmago"
6
	"github.com/privacybydesign/irmago/internal/keysharecore"
7
	"github.com/privacybydesign/irmago/server"
8
	"github.com/privacybydesign/irmago/server/keyshare/keyshareserver"
9
10
11
12
	"github.com/sietseringers/cobra"
	"github.com/sietseringers/viper"
)

13
var keyshareServerCmd = &cobra.Command{
14
15
	Use:   "server",
	Short: "IRMA keyshare server",
16
	Run: func(command *cobra.Command, args []string) {
17
18
19
20
		conf, err := configureKeyshareServer(command)
		if err != nil {
			die("failed to read configuration", err)
		}
21
22

		// Create main server
23
		keyshareServer, err := keyshareserver.New(conf)
24
25
26
27
		if err != nil {
			die("", err)
		}

28
		runServer(keyshareServer, conf.Logger)
29
30
31
32
	},
}

func init() {
33
	keyshareRootCmd.AddCommand(keyshareServerCmd)
34

35
36
37
38
39
40
41
42
43
44
45
	keyshareServerCmd.SetUsageTemplate(headerFlagsTemplate)
	flagHeaders["irma keyshare server"] = map[string]string{
		"port":               "Server address and port to listen on",
		"db-type":            "Database configuration",
		"jwt-privkey":        "Cryptographic keys",
		"keyshare-attribute": "Keyshare server attribute issued during registration",
		"email-server":       "Email configuration (leave empty to disable sending emails)",
		"tls-cert":           "TLS configuration (leave empty to disable TLS)",
		"verbose":            "Other options",
	}

46
	flags := keyshareServerCmd.Flags()
47
48
49
50
51
52
53
54
55
56
57
	flags.SortFlags = false
	flags.StringP("config", "c", "", "path to configuration file")
	flags.StringP("schemes-path", "s", irma.DefaultSchemesPath(), "path to irma_configuration")
	flags.String("schemes-assets-path", "", "if specified, copy schemes from here into --schemes-path")
	flags.Int("schemes-update", 60, "update IRMA schemes every x minutes (0 to disable)")
	flags.StringP("privkeys", "k", "", "path to IRMA private keys")
	flags.StringP("url", "u", "", "external URL to server to which the IRMA client connects, \":port\" being replaced by --port value")

	flags.IntP("port", "p", 8080, "port at which to listen")
	flags.StringP("listen-addr", "l", "", "address at which to listen (default 0.0.0.0)")

58
	flags.String("db-type", string(keyshareserver.DBTypePostgres), "Type of database to connect keyshare server to")
59
60
61
62
63
	flags.String("db", "", "Database server connection string")

	flags.String("jwt-privkey", "", "Private jwt key of keyshare server")
	flags.String("jwt-privkey-file", "", "Path to file containing private jwt key of keyshare server")
	flags.Int("jwt-privkey-id", 0, "Key identifier of keyshare server public key matching used private key")
64
65
	flags.String("jwt-issuer", keysharecore.JWTIssuerDefault, "JWT issuer used in \"iss\" field")
	flags.Int("jwt-pin-expiry", keysharecore.JWTPinExpiryDefault, "Expiry of PIN JWT in seconds")
66
67
68
	flags.String("storage-primary-keyfile", "", "Primary key used for encrypting and decrypting secure containers")
	flags.StringSlice("storage-fallback-keyfile", nil, "Fallback key(s) used to decrypt older secure containers")

69
	flags.String("keyshare-attribute", "", "Attribute identifier that contains username")
70
71
72
73
74
75

	flags.String("email-server", "", "Email server to use for sending email address confirmation emails")
	flags.String("email-hostname", "", "Hostname used in email server tls certificate (leave empty when mail server does not use tls)")
	flags.String("email-username", "", "Username to use when authenticating with email server")
	flags.String("email-password", "", "Password to use when authenticating with email server")
	flags.String("email-from", "", "Email address to use as sender address")
76
	flags.String("default-language", "en", "Default language, used as fallback when users preferred language is not available")
77
	flags.StringToString("registration-email-subjects", nil, "Translated subject lines for the registration email")
78
	flags.StringToString("registration-email-files", nil, "Translated emails for the registration email")
79
80
81
82
83
84
85
86
87
88
89
90
91
92
	flags.StringToString("verification-url", nil, "Base URL for the email verification link (localized)")

	flags.String("tls-cert", "", "TLS certificate (chain)")
	flags.String("tls-cert-file", "", "path to TLS certificate (chain)")
	flags.String("tls-privkey", "", "TLS private key")
	flags.String("tls-privkey-file", "", "path to TLS private key")
	flags.Bool("no-tls", false, "Disable TLS")

	flags.CountP("verbose", "v", "verbose (repeatable)")
	flags.BoolP("quiet", "q", false, "quiet")
	flags.Bool("log-json", false, "Log in JSON format")
	flags.Bool("production", false, "Production mode")
}

93
func configureKeyshareServer(cmd *cobra.Command) (*keyshareserver.Configuration, error) {
94
	readConfig(cmd, "keyshareserver", "keyshareserver", []string{".", "/etc/keyshareserver"}, nil)
95
96

	// And build the configuration
97
	conf := &keyshareserver.Configuration{
98
99
		Configuration:      configureIRMAServer(),
		EmailConfiguration: configureEmail(),
100

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
		DBType:    keyshareserver.DBType(viper.GetString("db_type")),
		DBConnStr: viper.GetString("db_str"),

		JwtKeyID:                viper.GetUint32("jwt_privkey_id"),
		JwtPrivateKey:           viper.GetString("jwt_privkey"),
		JwtPrivateKeyFile:       viper.GetString("jwt_privkey_file"),
		JwtIssuer:               viper.GetString("jwt_issuer"),
		JwtPinExpiry:            viper.GetInt("jwt_pin_expiry"),
		StoragePrimaryKeyFile:   viper.GetString("storage_primary_keyfile"),
		StorageFallbackKeyFiles: viper.GetStringSlice("storage_fallback_keyfile"),

		KeyshareAttribute: irma.NewAttributeTypeIdentifier(viper.GetString("keyshare_attribute")),

		RegistrationEmailSubjects: viper.GetStringMapString("registration_email_subjects"),
		RegistrationEmailFiles:    viper.GetStringMapString("registration_email_files"),
		VerificationURL:           viper.GetStringMapString("verification_url"),
117
	}
118

119
120
121
122
	if conf.Production && conf.DBType != keyshareserver.DBTypePostgres {
		return nil, errors.New("in production mode, db-type must be postgres")
	}

123
124
	conf.URL = server.ReplacePortString(viper.GetString("url"), viper.GetInt("port"))

125
	return conf, nil
126
}