blob: 8527ff6619f8c189a2a8b2c2d184899c7a7b7fee [file] [log] [blame]
Author Namea594e632018-08-10 11:33:58 -04001/*
2 Copyright 2017 the original author or authors.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17package main
18
19import (
20 "flag"
21 "fmt"
22 "log"
23 "net"
24 "net/http"
25 "os"
26 "strings"
27
28 "gerrit.opencord.org/abstract-olt/api"
29 "gerrit.opencord.org/abstract-olt/internal/pkg/settings"
30 "github.com/grpc-ecosystem/grpc-gateway/runtime"
31 "golang.org/x/net/context"
32 "google.golang.org/grpc"
33 "google.golang.org/grpc/credentials"
34 "google.golang.org/grpc/metadata"
35)
36
37// private type for Context keys
38type contextKey int
39
donNewtonAlphab3279ea2018-09-18 15:55:32 -040040var useSsl *bool
41var useAuthentication *bool
42var certDirectory *string
43
Author Namea594e632018-08-10 11:33:58 -040044const (
45 clientIDKey contextKey = iota
46)
47
48/*
49GetLogger - returns the logger
50*/
51func credMatcher(headerName string) (mdName string, ok bool) {
52 if headerName == "Login" || headerName == "Password" {
53 return headerName, true
54 }
55 return "", false
56}
57
58// authenticateAgent check the client credentials
59func authenticateClient(ctx context.Context, s *api.Server) (string, error) {
donNewtonAlphab3279ea2018-09-18 15:55:32 -040060 //TODO if we decide to handle Authentication with AbstractOLT this will need to be bound to an authentication service
Author Namea594e632018-08-10 11:33:58 -040061 if md, ok := metadata.FromIncomingContext(ctx); ok {
62 clientLogin := strings.Join(md["login"], "")
63 clientPassword := strings.Join(md["password"], "")
64
65 if clientLogin != "john" {
66 return "", fmt.Errorf("unknown user %s", clientLogin)
67 }
68 if clientPassword != "doe" {
69 return "", fmt.Errorf("bad password %s", clientPassword)
70 }
71
72 log.Printf("authenticated client: %s", clientLogin)
73 return "42", nil
74 }
75 return "", fmt.Errorf("missing credentials")
76}
77
78// unaryInterceptor call authenticateClient with current context
79func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
80 s, ok := info.Server.(*api.Server)
81 if !ok {
82 return nil, fmt.Errorf("unable to cast server")
83 }
84 clientID, err := authenticateClient(ctx, s)
85 if err != nil {
86 return nil, err
87 }
88
89 ctx = context.WithValue(ctx, clientIDKey, clientID)
90 return handler(ctx, req)
91}
92
93func startGRPCServer(address, certFile, keyFile string) error {
donNewtonAlphab3279ea2018-09-18 15:55:32 -040094 if settings.GetDebug() {
95 log.Printf("startGRPCServer(LisenAddress:%s,CertFile:%s,KeyFile:%s\n", address, certFile, keyFile)
96 }
Author Namea594e632018-08-10 11:33:58 -040097 // create a listener on TCP port
98 lis, err := net.Listen("tcp", address)
99 if err != nil {
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400100 log.Printf("startGRPCServer failed to start with %v\n", err)
Author Namea594e632018-08-10 11:33:58 -0400101 return fmt.Errorf("failed to listen: %v", err)
102 }
103
104 // create a server instance
105 s := api.Server{}
106
107 // Create the TLS credentials
108 creds, err := credentials.NewServerTLSFromFile(certFile, keyFile)
109 if err != nil {
110 return fmt.Errorf("could not load TLS keys: %s", err)
111 }
112
113 // Create an array of gRPC options with the credentials
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400114 var opts []grpc.ServerOption
115 if *useSsl && *useAuthentication {
116 opts = []grpc.ServerOption{grpc.Creds(creds),
117 grpc.UnaryInterceptor(unaryInterceptor)}
118 } else if *useAuthentication {
119 opts = []grpc.ServerOption{grpc.UnaryInterceptor(unaryInterceptor)}
120 } else if *useSsl {
121 opts = []grpc.ServerOption{grpc.Creds(creds)}
122 } else {
123 opts = []grpc.ServerOption{}
124 }
Author Namea594e632018-08-10 11:33:58 -0400125
126 // create a gRPC server object
127 grpcServer := grpc.NewServer(opts...)
128
129 // attach the Ping service to the server
donNewtonAlpha5234b132018-08-16 14:12:28 -0400130 api.RegisterAbstractOLTServer(grpcServer, &s)
Author Namea594e632018-08-10 11:33:58 -0400131
132 // start the server
133 log.Printf("starting HTTP/2 gRPC server on %s", address)
134 if err := grpcServer.Serve(lis); err != nil {
135 return fmt.Errorf("failed to serve: %s", err)
136 }
137
138 return nil
139}
140func startRESTServer(address, grpcAddress, certFile string) error {
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400141 if settings.GetDebug() {
142 log.Printf("startRESTServer(Address:%s, GRPCAddress:%s,Cert File:%s\n", address, grpcAddress, certFile)
143 }
Author Namea594e632018-08-10 11:33:58 -0400144 ctx := context.Background()
145 ctx, cancel := context.WithCancel(ctx)
146 defer cancel()
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400147 var mux *runtime.ServeMux
Author Namea594e632018-08-10 11:33:58 -0400148
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400149 if *useAuthentication {
150 mux = runtime.NewServeMux(runtime.WithIncomingHeaderMatcher(credMatcher))
151 } else {
152 mux = runtime.NewServeMux()
153 }
Author Namea594e632018-08-10 11:33:58 -0400154 creds, err := credentials.NewClientTLSFromFile(certFile, "")
155 if err != nil {
156 return fmt.Errorf("could not load TLS certificate: %s", err)
157 }
158
159 // Setup the client gRPC options
160 opts := []grpc.DialOption{grpc.WithTransportCredentials(creds)}
donNewtonAlpha5234b132018-08-16 14:12:28 -0400161 err = api.RegisterAbstractOLTHandlerFromEndpoint(ctx, mux, grpcAddress, opts)
Author Namea594e632018-08-10 11:33:58 -0400162 if err != nil {
163 return fmt.Errorf("could not register service Ping: %s", err)
164 }
165
166 log.Printf("starting HTTP/1.1 REST server on %s", address)
167 http.ListenAndServe(address, mux)
168
169 return nil
170}
171func main() {
172 debugPtr := flag.Bool("d", false, "Log Level Debug")
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400173 useAuthentication = flag.Bool("a", false, "Use Authentication")
174 useSsl = flag.Bool("s", false, "Use SSL")
175 certDirectory = flag.String("cert_dir", "cert", "Directory where key files exist")
176 listenAddress := flag.String("listenAddress", "localhost", "IP Address to listen on")
177 grpcPort := flag.String("grpc_port", "7777", "Port to listen for GRPC")
178 restPort := flag.String("rest_port", "7778", "Port to listen for Rest Server")
179 logFile := flag.String("log_file", "AbstractOLT.log", "Name of the LogFile to write to")
180 h := flag.Bool("h", false, "Show usage")
181 help := flag.Bool("help", false, "Show usage")
Author Namea594e632018-08-10 11:33:58 -0400182
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400183 flag.Parse()
184
185 if *help || *h {
186 var usage = `./AbstractOLT -d [default false] : Runs in Debug mode
187Params:
188 -s [default false] -cert_dir [default $WORKING_DIR/cert] DIR : Runs in SSL mode with server.crt and server.key found in DIR
189 -a [default false] : Run in Authentication mode currently very basic
190 -listenAddress IP_ADDRESS [default localhost] -grpc_port [default 7777] PORT1 -rest_port [default 7778] PORT2: Listen for grpc on IP_ADDRESS:PORT1 and rest on IP_ADDRESS:PORT2
191 -log_file [default $WORKING_DIR/AbstractOLT.log] LOG_FILE
192 -h(elp) print this usage
193`
194 fmt.Println(usage)
195 return
196 }
197 settings.SetDebug(*debugPtr)
198 fmt.Println("Startup Params: debug:", *debugPtr, " Authentication:", *useAuthentication, " SSL:", *useSsl, "Cert Directory", *certDirectory,
199 "ListenAddress:", *listenAddress, " grpc port:", *grpcPort, " rest port:", *restPort, "Logging to ", *logFile)
200
201 file, err := os.OpenFile(*logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
Author Namea594e632018-08-10 11:33:58 -0400202 if err != nil {
203 log.Fatalln("Failed to open log file", file, ":", err)
204 }
205 log.SetOutput(file)
206 log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile)
207 log.Printf("Setting Debug to %t\n", settings.GetDebug())
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400208 if settings.GetDebug() {
209 log.Println("Startup Params: debug:", *debugPtr, " Authentication:", *useAuthentication, " SSL:", *useSsl, "Cert Directory", *certDirectory,
210 "ListenAddress:", *listenAddress, " grpc port:", *grpcPort, " rest port:", *restPort, "Logging to ", *logFile)
211 }
Author Namea594e632018-08-10 11:33:58 -0400212
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400213 grpcAddress := fmt.Sprintf("%s:%s", *listenAddress, *grpcPort)
214 restAddress := fmt.Sprintf("%s:%s", *listenAddress, *restPort)
215
216 certFile := fmt.Sprintf("%s/server.crt", *certDirectory)
217 keyFile := fmt.Sprintf("%s/server.key", *certDirectory)
Author Namea594e632018-08-10 11:33:58 -0400218
219 // fire the gRPC server in a goroutine
220 go func() {
221 err := startGRPCServer(grpcAddress, certFile, keyFile)
222 if err != nil {
223 log.Fatalf("failed to start gRPC server: %s", err)
224 }
225 }()
226
227 // fire the REST server in a goroutine
228 go func() {
229 err := startRESTServer(restAddress, grpcAddress, certFile)
230 if err != nil {
231 log.Fatalf("failed to start gRPC server: %s", err)
232 }
233 }()
234
235 // infinite loop
236 log.Printf("Entering infinite loop")
237 select {}
donNewtonAlphab3279ea2018-09-18 15:55:32 -0400238 //TODO publish periodic stats etc
Author Namea594e632018-08-10 11:33:58 -0400239 fmt.Println("AbstractOLT")
240}