-
Notifications
You must be signed in to change notification settings - Fork 455
/
client.go
134 lines (117 loc) · 3.57 KB
/
client.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
127
128
129
130
131
132
133
134
package main
import (
"context"
"crypto/rand"
"crypto/x509"
"encoding/base64"
"errors"
"fmt"
"log"
"time"
bundlev1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/bundle/v1"
svidv1 "github.com/spiffe/spire-api-sdk/proto/spire/api/server/svid/v1"
"github.com/spiffe/spire-api-sdk/proto/spire/api/types"
"github.com/spiffe/spire/pkg/common/pemutil"
"github.com/spiffe/spire/test/integration/setup/itclient"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
)
var (
key, _ = pemutil.ParseSigner([]byte(`
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgs/CcKxAEIyBBEQ9h
ES2kJbWTz79ut45qAb0UgqrGqmOhRANCAARssWdfmS3D4INrpLBdSBxzso5kPPSX
F21JuznwCuYKNV5LnzhUA3nt2+6e18ZIXUDxl+CpkvCYc10MO6SYg6AE
-----END PRIVATE KEY-----
`))
)
func main() {
// Run all tests cases and if error msg is returned make client fails
if msg := run(); msg != "" {
log.Fatal(msg)
}
log.Println("Downstream client finished successfully")
}
// run executes all tests cases and return error msg when failing
func run() string {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
c := itclient.New(ctx)
defer c.Release()
failures := make(map[string]error)
// Validate call to New Downstream X509 CA
if err := validateNewDownstreamX509CA(ctx, c); err != nil {
failures["NewDownstreamX509CA"] = err
}
if err := validatePublishJWTAUthorirty(ctx, c); err != nil {
failures["PublishJWTAuthority"] = err
}
msg := ""
for rpcName, err := range failures {
msg += fmt.Sprintf("RPC %q: %v\n", rpcName, err)
}
return msg
}
func validateNewDownstreamX509CA(ctx context.Context, c *itclient.Client) error {
// Create csr
csr, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{}, key)
if err != nil {
return fmt.Errorf("failed to create CSR: %w", err)
}
// Create new svid client and new downstream CA
resp, err := c.SVIDClient().NewDownstreamX509CA(ctx, &svidv1.NewDownstreamX509CARequest{
Csr: csr,
})
switch {
case c.ExpectErrors:
return validatePermissionError(err)
case err != nil:
return fmt.Errorf("failed to call NewDownstreamX509CA: %w", err)
case len(resp.CaCertChain) == 0:
return errors.New("no CA returned")
case len(resp.X509Authorities) == 0:
return errors.New("no authorities returned")
}
return nil
}
func validatePublishJWTAUthorirty(ctx context.Context, c *itclient.Client) error {
// Marshal key
pkixBytes, err := base64.StdEncoding.DecodeString("MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYSlUVLqTD8DEnA4F1EWMTf5RXc5lnCxw+5WKJwngEL3rPc9i4Tgzz9riR3I/NiSlkgRO1WsxBusqpC284j9dXA==")
if err != nil {
return fmt.Errorf("unable to marshal key: %w", err)
}
jwtKey := &types.JWTKey{
PublicKey: pkixBytes,
ExpiresAt: time.Now().Add(time.Minute).Unix(),
KeyId: "authority1",
}
resp, err := c.BundleClient().PublishJWTAuthority(ctx, &bundlev1.PublishJWTAuthorityRequest{
JwtAuthority: jwtKey,
})
switch {
case c.ExpectErrors:
return validatePermissionError(err)
case err != nil:
return fmt.Errorf("failed to publish JWT authority: %w", err)
case len(resp.JwtAuthorities) == 0:
return errors.New("no authorities ruturned")
}
for _, a := range resp.JwtAuthorities {
if proto.Equal(jwtKey, a) {
// Authority appended
return nil
}
}
return errors.New("authority was not added")
}
func validatePermissionError(err error) error {
switch {
case err == nil:
return errors.New("no error returned")
case status.Code(err) != codes.PermissionDenied:
return fmt.Errorf("unnexpected error returned: %w", err)
default:
return nil
}
}