/
server.go
126 lines (109 loc) · 3.64 KB
/
server.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
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// The fake_server is a simple gRPC gnmi agent implementation which will take a
// configuration and start a listening service for the configured target.
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"flag"
log "github.com/golang/glog"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc"
"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/proto"
"github.com/openconfig/gnmi/testing/fake/gnmi"
fpb "github.com/openconfig/gnmi/testing/fake/proto"
)
var (
configFile = flag.String("config", "", "configuration file to load")
text = flag.Bool("text", false, "use text configuration file")
port = flag.Int("port", -1, "port to listen on")
caCert = flag.String("ca_crt", "", "CA certificate for client certificate validation. Optional.")
serverCert = flag.String("server_crt", "", "TLS server certificate")
serverKey = flag.String("server_key", "", "TLS server private key")
allowNoClientCert = flag.Bool("allow_no_client_auth", false, "When set, fake_server will request but not require a client certificate.")
tunnelAddr = flag.String("tunnel_addr", "", "tunnel server address")
tunnelCrt = flag.String("tunnel_crt", "", "tunnel server cert file")
)
func loadConfig(fileName string) (*fpb.Config, error) {
in, err := ioutil.ReadFile(fileName)
if err != nil {
return nil, err
}
cfg := &fpb.Config{}
if *text {
if err := prototext.Unmarshal(in, cfg); err != nil {
return nil, fmt.Errorf("failed to parse text file %s: %v", fileName, err)
}
} else {
if err := proto.Unmarshal(in, cfg); err != nil {
return nil, fmt.Errorf("failed to parse %s: %v", fileName, err)
}
}
return cfg, nil
}
func main() {
flag.Parse()
switch {
case *configFile == "":
log.Errorf("config must be set.")
return
case *port < 0:
log.Errorf("port must be >= 0.")
return
}
cfg, err := loadConfig(*configFile)
if err != nil {
log.Errorf("Failed to load %s: %v", *configFile, err)
return
}
certificate, err := tls.LoadX509KeyPair(*serverCert, *serverKey)
if err != nil {
log.Exitf("could not load server key pair: %s", err)
}
tlsCfg := &tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
Certificates: []tls.Certificate{certificate},
}
if *allowNoClientCert {
// RequestClientCert will ask client for a certificate but won't
// require it to proceed. If certificate is provided, it will be
// verified.
tlsCfg.ClientAuth = tls.RequestClientCert
}
if *caCert != "" {
ca, err := ioutil.ReadFile(*caCert)
if err != nil {
log.Exitf("could not read CA certificate: %s", err)
}
certPool := x509.NewCertPool()
if ok := certPool.AppendCertsFromPEM(ca); !ok {
log.Exit("failed to append CA certificate")
}
tlsCfg.ClientCAs = certPool
}
opts := []grpc.ServerOption{grpc.Creds(credentials.NewTLS(tlsCfg))}
cfg.Port = int32(*port)
cfg.TunnelAddr = *tunnelAddr
cfg.TunnelCrt = *tunnelCrt
a, err := gnmi.New(cfg, opts)
if err != nil {
log.Errorf("Failed to create gNMI server: %v", err)
return
}
log.Infof("Starting RPC server on address: %s", a.Address())
select {} // block forever
}