-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
147 lines (122 loc) · 3.88 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package main
import (
"encoding/json"
"fmt"
"os"
"strings"
irma "github.com/privacybydesign/irmago"
"github.com/privacybydesign/irmago/server"
"github.com/privacybydesign/irmago/server/irmaserver"
)
var logger = server.NewLogger(0, false, false)
const authTokenMinLength = 20
type Configuration struct {
*server.Configuration
ClientAttr irma.AttributeTypeIdentifier `json:"client_attr"`
LoginCodeAttr irma.AttributeTypeIdentifier `json:"logincode_attr"`
LoginCodeLength uint `json:"logincode_length"`
ListenAddress string `json:"listen_addr"`
Port uint `json:"port"`
Clients map[string]Client `json:"clients"`
// TLS configuration
TLSCertificateFile string `json:"tls_cert_file"`
TLSPrivateKeyFile string `json:"tls_privkey_file"`
}
type Client struct {
Name string `json:"name"`
Domain string `json:"domain"`
}
func main() {
if len(os.Args) != 2 {
msg := fmt.Sprintf("%d arguments received, 1 expected: pass path to JSON configuration file as argument", len(os.Args)-1)
die(msg, nil)
}
bts, err := os.ReadFile(os.Args[1])
if err != nil {
die("failed to read configuration file", err)
}
conf := new(Configuration)
if err = json.Unmarshal(bts, conf); err != nil {
die("failed to unmarshal configuration", err)
}
conf.Logger = logger
logger.Level = server.Verbosity(conf.Verbose)
checkConfig(conf)
if err = start(conf); err != nil {
die("failed to start server", err)
}
}
func checkConfig(conf *Configuration) {
if len(conf.Clients) == 0 {
die("no clients configured", nil)
}
for auth, client := range conf.Clients {
if client.Name == "" {
die(fmt.Sprintf("client with authorization token %s has empty name", auth), nil)
}
if client.Domain == "" {
die(fmt.Sprintf("client %s has empty domain name", client.Name), nil)
}
if len(auth) < authTokenMinLength {
msg := fmt.Sprintf(
"client %s has authentication token of length %d, should have at least length %d",
client, len(auth), authTokenMinLength,
)
die(msg, nil)
}
}
if conf.URL == "" {
localIP, err := server.LocalIP()
if err != nil {
die("failed to determine local IP", err)
}
conf.URL = fmt.Sprintf("http://%s:%d/irma", localIP, conf.Port)
} else {
// conf.URL has to point to the endpoints for the IRMA app which are mounted at /irma/
if !strings.HasSuffix(conf.URL, "/") {
conf.URL += "/"
}
if !strings.HasSuffix(conf.URL, "irma/") {
conf.URL += "irma/"
}
}
if (conf.TLSPrivateKeyFile != "" && conf.TLSCertificateFile == "") ||
(conf.TLSCertificateFile != "" && conf.TLSPrivateKeyFile == "") {
die("either configure both or none of tls_cert_file and tls_privkey_file", nil)
}
if err := irmaserver.Initialize(conf.Configuration); err != nil {
die("failed to configure IRMA server", err)
}
if conf.ClientAttr.CredentialTypeIdentifier() != conf.LoginCodeAttr.CredentialTypeIdentifier() {
msg := fmt.Sprintf("attributes %s and %s do not belong to the same credential type", conf.ClientAttr, conf.LoginCodeAttr)
die(msg, nil)
}
irmaconf := conf.Configuration.IrmaConfiguration
credid := conf.ClientAttr.CredentialTypeIdentifier()
credtype := irmaconf.CredentialTypes[credid]
if credtype == nil {
die("nonexistent credential type: "+credid.String(), nil)
}
for _, attr := range []irma.AttributeTypeIdentifier{conf.ClientAttr, conf.LoginCodeAttr} {
if !credtype.ContainsAttribute(attr) {
die(fmt.Sprintf("credential type %s has no attribute %s", credid, attr.Name()), nil)
}
}
if conf.LoginCodeLength == 0 {
conf.LoginCodeLength = loginCodeDefaultLength
}
}
func (conf *Configuration) clientDomains() []string {
domains := make([]string, 0, len(conf.Clients))
for _, client := range conf.Clients {
domains = append(domains, client.Domain)
}
return domains
}
func die(message string, err error) {
if err != nil {
message = fmt.Sprintf("%s: %s", message, err)
}
logger.Error(message)
os.Exit(1)
}