-
Notifications
You must be signed in to change notification settings - Fork 118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Authentication, Authorization, HTTPS support #773
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,153 @@ | ||||||||||||||||||
/* | ||||||||||||||||||
Package sdk is the gRPC implementation of the SDK gRPC server | ||||||||||||||||||
Copyright 2018 Portworx | ||||||||||||||||||
|
||||||||||||||||||
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. | ||||||||||||||||||
*/ | ||||||||||||||||||
package sdk | ||||||||||||||||||
|
||||||||||||||||||
import ( | ||||||||||||||||||
"context" | ||||||||||||||||||
"fmt" | ||||||||||||||||||
"mime" | ||||||||||||||||||
"net/http" | ||||||||||||||||||
|
||||||||||||||||||
"github.com/gobuffalo/packr" | ||||||||||||||||||
"github.com/grpc-ecosystem/grpc-gateway/runtime" | ||||||||||||||||||
"github.com/sirupsen/logrus" | ||||||||||||||||||
"google.golang.org/grpc" | ||||||||||||||||||
|
||||||||||||||||||
"github.com/libopenstorage/openstorage/api" | ||||||||||||||||||
"github.com/libopenstorage/openstorage/pkg/grpcserver" | ||||||||||||||||||
) | ||||||||||||||||||
|
||||||||||||||||||
type sdkRestGateway struct { | ||||||||||||||||||
config ServerConfig | ||||||||||||||||||
restPort string | ||||||||||||||||||
grpcServer *sdkGrpcServer | ||||||||||||||||||
server *http.Server | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
func newSdkRestGateway(config *ServerConfig, grpcServer *sdkGrpcServer) (*sdkRestGateway, error) { | ||||||||||||||||||
return &sdkRestGateway{ | ||||||||||||||||||
config: *config, | ||||||||||||||||||
restPort: config.RestPort, | ||||||||||||||||||
grpcServer: grpcServer, | ||||||||||||||||||
}, nil | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
func (s *sdkRestGateway) Start() error { | ||||||||||||||||||
mux, err := s.restServerSetupHandlers() | ||||||||||||||||||
if err != nil { | ||||||||||||||||||
return err | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
// Create object here so that we can access its Close receiver. | ||||||||||||||||||
address := ":" + s.restPort | ||||||||||||||||||
s.server = &http.Server{ | ||||||||||||||||||
Addr: address, | ||||||||||||||||||
Handler: mux, | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
ready := make(chan bool) | ||||||||||||||||||
go func() { | ||||||||||||||||||
ready <- true | ||||||||||||||||||
var err error | ||||||||||||||||||
if s.config.Tls != nil { | ||||||||||||||||||
err = s.server.ListenAndServeTLS(s.config.Tls.CertFile, s.config.Tls.KeyFile) | ||||||||||||||||||
} else { | ||||||||||||||||||
err = s.server.ListenAndServe() | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
if err == http.ErrServerClosed || err == nil { | ||||||||||||||||||
return | ||||||||||||||||||
} else { | ||||||||||||||||||
logrus.Fatalf("Unable to start SDK REST gRPC Gateway: %s\n", | ||||||||||||||||||
err.Error()) | ||||||||||||||||||
} | ||||||||||||||||||
}() | ||||||||||||||||||
<-ready | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the purpose of this just to block until we know the goroutine has started? I suppose you could use a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. correct 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, this code is copied from the older server.go |
||||||||||||||||||
logrus.Infof("SDK gRPC REST Gateway started on port :%s", s.restPort) | ||||||||||||||||||
|
||||||||||||||||||
return nil | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
func (s *sdkRestGateway) Stop() { | ||||||||||||||||||
if err := s.server.Close(); err != nil { | ||||||||||||||||||
logrus.Fatalf("REST GW STOP error: %v", err) | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should also add a Stop routine for the REST gateway. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's much harder to do. It has to do with http server in golang. If it is supports it in later golang versions, I will add it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is how we can do it
Suggested change
|
||||||||||||||||||
// restServerSetupHandlers sets up the handlers to the swagger ui and | ||||||||||||||||||
// to the gRPC REST Gateway. | ||||||||||||||||||
func (s *sdkRestGateway) restServerSetupHandlers() (*http.ServeMux, error) { | ||||||||||||||||||
|
||||||||||||||||||
// Create an HTTP server router | ||||||||||||||||||
mux := http.NewServeMux() | ||||||||||||||||||
|
||||||||||||||||||
// Swagger files using packr | ||||||||||||||||||
swaggerUIBox := packr.NewBox("./swagger-ui") | ||||||||||||||||||
swaggerJSONBox := packr.NewBox("./api") | ||||||||||||||||||
mime.AddExtensionType(".svg", "image/svg+xml") | ||||||||||||||||||
|
||||||||||||||||||
// Handler to return swagger.json | ||||||||||||||||||
mux.HandleFunc("/swagger.json", func(w http.ResponseWriter, r *http.Request) { | ||||||||||||||||||
w.Write(swaggerJSONBox.Bytes("api.swagger.json")) | ||||||||||||||||||
}) | ||||||||||||||||||
|
||||||||||||||||||
// Handler to access the swagger ui. The UI pulls the swagger | ||||||||||||||||||
// json file from /swagger.json | ||||||||||||||||||
// The link below MUST have th last '/'. It is really important. | ||||||||||||||||||
prefix := "/swagger-ui/" | ||||||||||||||||||
mux.Handle(prefix, | ||||||||||||||||||
http.StripPrefix(prefix, http.FileServer(swaggerUIBox))) | ||||||||||||||||||
|
||||||||||||||||||
// Create a router just for HTTP REST gRPC Server Gateway | ||||||||||||||||||
gmux := runtime.NewServeMux() | ||||||||||||||||||
|
||||||||||||||||||
// Connect to gRPC unix domain socket | ||||||||||||||||||
conn, err := grpcserver.Connect( | ||||||||||||||||||
s.grpcServer.Address(), | ||||||||||||||||||
[]grpc.DialOption{grpc.WithInsecure()}) | ||||||||||||||||||
if err != nil { | ||||||||||||||||||
return nil, fmt.Errorf("Failed to connect to gRPC handler: %v", err) | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
// REST Gateway Handlers | ||||||||||||||||||
handlers := []func(context.Context, *runtime.ServeMux, *grpc.ClientConn) (err error){ | ||||||||||||||||||
api.RegisterOpenStorageClusterHandler, | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about this list of functions is a global variable. So that we can add tests, to ensure if anyone adds a new handler it gets added to this list. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a good idea. Do you mind if we add this as a PR after this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes that works. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Issue #776 created |
||||||||||||||||||
api.RegisterOpenStorageNodeHandler, | ||||||||||||||||||
api.RegisterOpenStorageVolumeHandler, | ||||||||||||||||||
api.RegisterOpenStorageObjectstoreHandler, | ||||||||||||||||||
api.RegisterOpenStorageCredentialsHandler, | ||||||||||||||||||
api.RegisterOpenStorageSchedulePolicyHandler, | ||||||||||||||||||
api.RegisterOpenStorageCloudBackupHandler, | ||||||||||||||||||
api.RegisterOpenStorageIdentityHandler, | ||||||||||||||||||
api.RegisterOpenStorageMountAttachHandler, | ||||||||||||||||||
api.RegisterOpenStorageAlertsHandler, | ||||||||||||||||||
api.RegisterOpenStorageClusterPairHandler, | ||||||||||||||||||
api.RegisterOpenStorageMigrateHandler, | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
// Register the REST Gateway handlers | ||||||||||||||||||
for _, handler := range handlers { | ||||||||||||||||||
err := handler(context.Background(), gmux, conn) | ||||||||||||||||||
if err != nil { | ||||||||||||||||||
return nil, err | ||||||||||||||||||
} | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
// Pass all other unhandled paths to the gRPC gateway | ||||||||||||||||||
mux.Handle("/", gmux) | ||||||||||||||||||
return mux, nil | ||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for not making this a pointer? Just to ensure we make a copy of the config?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct.