-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for Named Pipes in Windows (#190)
* Introduce the WithNamedPipeName option to support named pipes (Windows only) Signed-off-by: Agustín Martínez Fayó <[email protected]>
- Loading branch information
1 parent
7e161c4
commit 6fd5a8f
Showing
10 changed files
with
207 additions
and
19 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
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,44 @@ | ||
//go:build windows | ||
// +build windows | ||
|
||
package fakeworkloadapi | ||
|
||
import ( | ||
"fmt" | ||
"math/rand" | ||
"testing" | ||
"time" | ||
|
||
"github.com/Microsoft/go-winio" | ||
"github.com/spiffe/go-spiffe/v2/proto/spiffe/workload" | ||
"github.com/stretchr/testify/require" | ||
"google.golang.org/grpc" | ||
) | ||
|
||
func NewWithNamedPipeListener(tb testing.TB) *WorkloadAPI { | ||
w := &WorkloadAPI{ | ||
x509Chans: make(map[chan *workload.X509SVIDResponse]struct{}), | ||
jwtBundlesChans: make(map[chan *workload.JWTBundlesResponse]struct{}), | ||
} | ||
|
||
listener, err := winio.ListenPipe(fmt.Sprintf(`\\.\pipe\go-spiffe-test-pipe-%x`, rand.Uint64()), nil) | ||
require.NoError(tb, err) | ||
|
||
server := grpc.NewServer() | ||
workload.RegisterSpiffeWorkloadAPIServer(server, &workloadAPIWrapper{w: w}) | ||
|
||
w.wg.Add(1) | ||
go func() { | ||
defer w.wg.Done() | ||
_ = server.Serve(listener) | ||
}() | ||
|
||
w.addr = listener.Addr().String() | ||
tb.Logf("WorkloadAPI address: %s", w.addr) | ||
w.server = server | ||
return w | ||
} | ||
|
||
func init() { | ||
rand.Seed(time.Now().UnixNano()) | ||
} |
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,29 @@ | ||
//go:build !windows | ||
// +build !windows | ||
|
||
package workloadapi | ||
|
||
import "errors" | ||
|
||
// appendDialOptionsOS appends OS specific dial options | ||
func (c *Client) appendDialOptionsOS() { | ||
// No options to add in this platform | ||
} | ||
func (c *Client) setAddress() error { | ||
if c.config.namedPipeName != "" { | ||
// Purely defensive. This should never happen. | ||
return errors.New("named pipes not supported in this platform") | ||
} | ||
|
||
if c.config.address == "" { | ||
var ok bool | ||
c.config.address, ok = GetDefaultAddress() | ||
if !ok { | ||
return errors.New("workload endpoint socket address is not configured") | ||
} | ||
} | ||
|
||
var err error | ||
c.config.address, err = parseTargetFromAddr(c.config.address) | ||
return 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
//go:build windows | ||
// +build windows | ||
|
||
package workloadapi | ||
|
||
import ( | ||
"errors" | ||
"path/filepath" | ||
|
||
"github.com/Microsoft/go-winio" | ||
"google.golang.org/grpc" | ||
) | ||
|
||
// appendDialOptionsOS appends OS specific dial options | ||
func (c *Client) appendDialOptionsOS() { | ||
if c.config.namedPipeName != "" { | ||
// Use the dialer to connect to named pipes only if a named pipe | ||
// is defined (i.e. WithNamedPipeName is used). | ||
c.config.dialOptions = append(c.config.dialOptions, grpc.WithContextDialer(winio.DialPipeContext)) | ||
} | ||
} | ||
|
||
func (c *Client) setAddress() error { | ||
var err error | ||
if c.config.namedPipeName != "" { | ||
if c.config.address != "" { | ||
return errors.New("only one of WithAddr or WithNamedPipeName options can be used, not both") | ||
} | ||
c.config.address = namedPipeTarget(c.config.namedPipeName) | ||
return nil | ||
} | ||
|
||
if c.config.address == "" { | ||
var ok bool | ||
c.config.address, ok = GetDefaultAddress() | ||
if !ok { | ||
return errors.New("workload endpoint socket address is not configured") | ||
} | ||
} | ||
|
||
c.config.address, err = parseTargetFromAddr(c.config.address) | ||
return err | ||
} | ||
|
||
// namedPipeTarget returns a target string suitable for | ||
// dialing the endpoint address based on the provided | ||
// pipe name. | ||
func namedPipeTarget(pipeName string) string { | ||
return `\\.\` + filepath.Join("pipe", pipeName) | ||
} |
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,53 @@ | ||
//go:build windows | ||
// +build windows | ||
|
||
package workloadapi | ||
|
||
import ( | ||
"context" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/spiffe/go-spiffe/v2/internal/test" | ||
"github.com/spiffe/go-spiffe/v2/internal/test/fakeworkloadapi" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestWithNamedPipeName(t *testing.T) { | ||
ca := test.NewCA(t, td) | ||
wl := fakeworkloadapi.NewWithNamedPipeListener(t) | ||
defer wl.Stop() | ||
|
||
pipeName := getPipeName(wl.Addr()) | ||
c, err := New(context.Background(), WithNamedPipeName(pipeName)) | ||
require.NoError(t, err) | ||
defer c.Close() | ||
require.Equal(t, pipeName, c.config.namedPipeName) | ||
|
||
resp := &fakeworkloadapi.X509SVIDResponse{ | ||
Bundle: ca.X509Bundle(), | ||
SVIDs: makeX509SVIDs(ca, fooID, barID), | ||
} | ||
wl.SetX509SVIDResponse(resp) | ||
svid, err := c.FetchX509SVID(context.Background()) | ||
require.NoError(t, err) | ||
assertX509SVID(t, svid, fooID, resp.SVIDs[0].Certificates) | ||
} | ||
|
||
func TestWithNamedPipeNameError(t *testing.T) { | ||
wl := fakeworkloadapi.NewWithNamedPipeListener(t) | ||
defer wl.Stop() | ||
|
||
c, err := New(context.Background(), WithNamedPipeName("ohno")) | ||
require.NoError(t, err) | ||
defer c.Close() | ||
|
||
wl.SetX509SVIDResponse(&fakeworkloadapi.X509SVIDResponse{}) | ||
_, err = c.FetchX509SVID(context.Background()) | ||
require.Error(t, err) | ||
require.Contains(t, err.Error(), `ohno: The system cannot find the file specified`) | ||
} | ||
|
||
func getPipeName(s string) string { | ||
return strings.TrimPrefix(s, `\\.\pipe`) | ||
} |
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,12 @@ | ||
//go:build windows | ||
// +build windows | ||
|
||
package workloadapi | ||
|
||
// WithNamedPipeName provides a Pipe Name for the Workload API | ||
// endpoint in the form \\.\pipe\<pipeName>. | ||
func WithNamedPipeName(pipeName string) ClientOption { | ||
return clientOption(func(c *clientConfig) { | ||
c.namedPipeName = pipeName | ||
}) | ||
} |