-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathclient.go
More file actions
116 lines (94 loc) · 2.8 KB
/
client.go
File metadata and controls
116 lines (94 loc) · 2.8 KB
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
package boundarysecrets
import (
"context"
"errors"
"fmt"
"time"
boundary "github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/authmethods"
)
const (
tokenExpirationTimeAttribName = "expiration_time"
loginNameAttribName = "login_name"
passwordAttribName = "password"
tokenAttribName = "token"
)
type boundaryClient struct {
*boundary.Client
tokenExp time.Time
config *boundaryConfig
}
// newClient creates a new boundary client and authenticates it with the
// provided configuration
func newClient(config *boundaryConfig) (*boundaryClient, error) {
if config == nil {
return nil, errors.New("client configuration was nil")
}
if config.LoginName == "" {
return nil, errors.New("login name was not defined")
}
if config.Password == "" {
return nil, errors.New("password was not defined")
}
if config.Addr == "" {
return nil, errors.New("boundary address was not defined")
}
if config.AuthMethodId == "" {
return nil, errors.New("auth-method ID was not defined")
}
cfg := boundary.Config{
Addr: config.Addr,
}
client, err := boundary.NewClient(&cfg)
if err != nil {
return nil, err
}
c := &boundaryClient{
Client: client,
config: config,
}
if err := c.authenticate(); err != nil {
return nil, fmt.Errorf("unable to authenticate new client: %w", err)
}
return c, nil
}
// authenticate authenticates the client with the provided configuration. The
// client and configuration must not be nil. The client's token expiration time
// and token are set as a result of a successful authentication.
func (c *boundaryClient) authenticate() error {
switch {
case c.Client == nil:
return errors.New("client was nil")
case c.config == nil:
return errors.New("client configuration was nil")
}
credentials := map[string]interface{}{
loginNameAttribName: c.config.LoginName,
passwordAttribName: c.config.Password,
}
amClient := authmethods.NewClient(c.Client)
authenticationResult, err := amClient.Authenticate(context.Background(), c.config.AuthMethodId, "login", credentials)
if err != nil {
return err
}
c.Client.SetToken(fmt.Sprint(authenticationResult.Attributes[tokenAttribName]))
rawExp, ok := authenticationResult.Attributes[tokenExpirationTimeAttribName]
if !ok {
return errors.New("expiration_time was not defined")
}
timeString, ok := rawExp.(string)
if !ok {
return errors.New("expiration_time was not a string")
}
parsedTime, err := time.Parse(time.RFC3339, timeString)
if err != nil {
return err
}
c.tokenExp = parsedTime
return nil
}
// tokenIsExpired returns true if the client's token has expired. We provide a
// 1 minute buffer to ensure that the token is not expired when we use it.
func (c *boundaryClient) tokenIsExpired() bool {
return time.Now().After(c.tokenExp.Add(-1 * time.Minute))
}