-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from andrejtokarcik/feat/authn
mTLS authentication w/ tests
- Loading branch information
Showing
31 changed files
with
1,044 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
"google.golang.org/grpc" | ||
) | ||
|
||
func DialContextWithTimeout(ctx context.Context, timeout time.Duration, target string, opts ...grpc.DialOption) (*grpc.ClientConn, error) { | ||
ctxWithTimeout, cancel := context.WithTimeout(ctx, timeout) | ||
defer cancel() | ||
|
||
return grpc.DialContext( | ||
ctxWithTimeout, | ||
target, | ||
append( | ||
opts, | ||
grpc.WithReturnConnectionError(), | ||
)..., | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,50 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"flag" | ||
"log" | ||
"time" | ||
|
||
"google.golang.org/grpc" | ||
|
||
"github.com/andrejtokarcik/jobworker/client" | ||
"github.com/andrejtokarcik/jobworker/mtls" | ||
) | ||
|
||
var ( | ||
serverAddress string | ||
connTimeout time.Duration | ||
credsFiles mtls.CredsFiles | ||
) | ||
|
||
func init() { | ||
flag.StringVar(&serverAddress, "server", "127.0.0.1:50051", "Address of the server to connect to") | ||
flag.DurationVar(&connTimeout, "timeout", 5*time.Second, "Connection timeout") | ||
|
||
flag.StringVar(&credsFiles.Cert, "client-cert", "client.crt", "Certificate file to use for the client") | ||
flag.StringVar(&credsFiles.Key, "client-key", "client.key", "Private key file to use for the client") | ||
flag.StringVar(&credsFiles.PeerCACert, "server-ca-cert", "server-ca.crt", "Certificate file of the CA to authenticate the server") | ||
} | ||
|
||
func main() { | ||
flag.Parse() | ||
|
||
creds, err := mtls.NewClientCreds(credsFiles) | ||
if err != nil { | ||
log.Fatal("Failed to load mTLS credentials: ", err) | ||
} | ||
|
||
conn, err := client.DialContextWithTimeout( | ||
context.Background(), | ||
connTimeout, | ||
serverAddress, | ||
grpc.WithTransportCredentials(creds), | ||
) | ||
if err != nil { | ||
log.Fatal("Failed to dial server: ", err) | ||
} | ||
defer conn.Close() | ||
|
||
log.Print("Successfully connected to server at ", serverAddress) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,46 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"log" | ||
"net" | ||
|
||
"google.golang.org/grpc" | ||
|
||
"github.com/andrejtokarcik/jobworker/mtls" | ||
"github.com/andrejtokarcik/jobworker/server" | ||
) | ||
|
||
var ( | ||
grpcPort int | ||
credsFiles mtls.CredsFiles | ||
) | ||
|
||
func init() { | ||
flag.IntVar(&grpcPort, "grpc-port", 50051, "Port to expose the gRPC server on") | ||
|
||
flag.StringVar(&credsFiles.Cert, "server-cert", "server.crt", "Certificate file to use for the server") | ||
flag.StringVar(&credsFiles.Key, "server-key", "server.key", "Private key file to use for the server") | ||
flag.StringVar(&credsFiles.PeerCACert, "client-ca-cert", "client-ca.crt", "Certificate file of the CA to authenticate the clients") | ||
} | ||
|
||
func main() { | ||
flag.Parse() | ||
|
||
creds, err := mtls.NewServerCreds(credsFiles) | ||
if err != nil { | ||
log.Fatal("Failed to load mTLS credentials: ", err) | ||
} | ||
grpcServer := server.New(grpc.Creds(creds)) | ||
|
||
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", grpcPort)) | ||
if err != nil { | ||
log.Fatal("Failed to listen: ", err) | ||
} | ||
|
||
log.Print("Starting gRPC server at ", listener.Addr()) | ||
if err := grpcServer.Serve(listener); err != nil { | ||
log.Fatal("Failed to serve: ", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package mtls_test | ||
|
||
import ( | ||
"context" | ||
"net" | ||
"time" | ||
|
||
"github.com/stretchr/testify/suite" | ||
"google.golang.org/grpc" | ||
"google.golang.org/grpc/test/bufconn" | ||
|
||
"github.com/andrejtokarcik/jobworker/client" | ||
"github.com/andrejtokarcik/jobworker/server" | ||
) | ||
|
||
type BufconnConfig struct { | ||
BufSize int | ||
ClientTimeout time.Duration | ||
} | ||
|
||
type BufconnSuite struct { | ||
suite.Suite | ||
BufconnConfig | ||
grpcServer *grpc.Server | ||
listener *bufconn.Listener | ||
} | ||
|
||
func NewBufconnSuite() (suite BufconnSuite) { | ||
suite.BufconnConfig = BufconnConfig{ | ||
BufSize: 1024 * 1024, | ||
ClientTimeout: 1 * time.Second, | ||
} | ||
return | ||
} | ||
|
||
func (suite *BufconnSuite) SetupBufconn(opts ...grpc.ServerOption) { | ||
suite.grpcServer = server.New(opts...) | ||
suite.listener = bufconn.Listen(suite.BufSize) | ||
go func() { | ||
if err := suite.grpcServer.Serve(suite.listener); err != nil { | ||
panic(err) | ||
} | ||
}() | ||
} | ||
|
||
func (suite *BufconnSuite) TearDownBufconn() { | ||
suite.listener.Close() | ||
suite.grpcServer.Stop() | ||
} | ||
|
||
func (suite *BufconnSuite) contextDialer(context.Context, string) (net.Conn, error) { | ||
return suite.listener.Dial() | ||
} | ||
|
||
func (suite *BufconnSuite) DialBufconn(serverName string, opts ...grpc.DialOption) (*grpc.ClientConn, error) { | ||
return client.DialContextWithTimeout( | ||
context.Background(), | ||
suite.ClientTimeout, | ||
serverName, | ||
append( | ||
opts, | ||
grpc.WithContextDialer(suite.contextDialer), | ||
)..., | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package mtls | ||
|
||
import ( | ||
"crypto/tls" | ||
"crypto/x509" | ||
"errors" | ||
"io/ioutil" | ||
|
||
"google.golang.org/grpc/credentials" | ||
) | ||
|
||
type CredsFiles struct { | ||
Cert, Key, PeerCACert string | ||
} | ||
|
||
type loadedCredsFiles struct { | ||
cert tls.Certificate | ||
peerCAPool *x509.CertPool | ||
} | ||
|
||
func loadCredsFiles(credsFiles CredsFiles) (*loadedCredsFiles, error) { | ||
cert, err := tls.LoadX509KeyPair(credsFiles.Cert, credsFiles.Key) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
peerCACert, err := ioutil.ReadFile(credsFiles.PeerCACert) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
peerCAPool := x509.NewCertPool() | ||
if ok := peerCAPool.AppendCertsFromPEM(peerCACert); !ok { | ||
return nil, errors.New("failed to append to peer CA cert pool") | ||
} | ||
|
||
return &loadedCredsFiles{cert, peerCAPool}, nil | ||
} | ||
|
||
func NewServerCreds(serverFiles CredsFiles) (credentials.TransportCredentials, error) { | ||
loaded, err := loadCredsFiles(serverFiles) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
config := &tls.Config{ | ||
Certificates: []tls.Certificate{loaded.cert}, | ||
ClientAuth: tls.RequireAndVerifyClientCert, | ||
ClientCAs: loaded.peerCAPool, | ||
} | ||
return credentials.NewTLS(config), nil | ||
} | ||
|
||
func NewClientCreds(clientFiles CredsFiles) (credentials.TransportCredentials, error) { | ||
loaded, err := loadCredsFiles(clientFiles) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
config := &tls.Config{ | ||
Certificates: []tls.Certificate{loaded.cert}, | ||
RootCAs: loaded.peerCAPool, | ||
} | ||
return credentials.NewTLS(config), nil | ||
} |
Oops, something went wrong.