This repository has been archived by the owner on May 18, 2018. It is now read-only.
/
account_check.go
151 lines (119 loc) · 3.57 KB
/
account_check.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package auth
import (
"context"
"github.com/jackc/pgx"
triton "github.com/joyent/triton-go"
"github.com/joyent/triton-go/account"
"github.com/joyent/triton-go/authentication"
"github.com/joyent/triton-service-groups/accounts"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)
type AccountCheck struct {
*ParsedRequest
*accounts.Account
TritonAccount *account.Account
config *triton.ClientConfig
store *accounts.Store
enableWhitelist bool
}
func NewAccountCheck(req *ParsedRequest, store *accounts.Store, cfg Config) *AccountCheck {
signer := &authentication.TestSigner{}
config := &triton.ClientConfig{
TritonURL: cfg.AuthURL,
AccountName: req.AccountName,
Signers: []authentication.Signer{signer},
}
return &AccountCheck{
ParsedRequest: req,
config: config,
store: store,
enableWhitelist: cfg.EnableWhitelist,
}
}
// newClient constructs our Triton AccountClient
func (ac *AccountCheck) newClient() (*account.AccountClient, error) {
return account.NewClient(ac.config)
}
func (ac *AccountCheck) OnTriton(ctx context.Context) error {
a, err := ac.newClient()
if err != nil {
return errors.Wrap(err, "failed to create account client")
}
a.SetHeader(ac.ParsedRequest.Header())
acct, err := a.Get(ctx, &account.GetInput{})
if err != nil {
log.Debug().
Str("account_name", ac.ParsedRequest.AccountName).
Msg("failed to get account")
return errors.Wrap(err, "failed to get account")
}
ac.TritonAccount = acct
return nil
}
func (ac *AccountCheck) createAccount(ctx context.Context) error {
newAccount := accounts.New(ac.store)
newAccount.AccountName = ac.TritonAccount.Login
newAccount.TritonUUID = ac.TritonAccount.ID
if err := newAccount.Insert(ctx); err != nil {
return errors.Wrapf(err, "failed to insert %q account", newAccount.AccountName)
}
ac.Account = newAccount
log.Debug().
Str("account_id", ac.Account.ID).
Str("account_name", ac.Account.AccountName).
Str("triton_uuid", ac.Account.TritonUUID).
Msg("auth: inserted new account into database")
return nil
}
// Save saves the TSG account from the Triton Account.
func (ac *AccountCheck) SaveAccount(ctx context.Context) error {
var exists bool
curAccount, err := ac.store.FindByName(ctx, ac.TritonAccount.Login)
switch err {
case nil:
exists = true
case pgx.ErrNoRows:
exists = false
default:
return err
}
if !exists && ac.enableWhitelist {
log.Debug().
Str("account_name", ac.TritonAccount.Login).
Str("triton_uuid", ac.TritonAccount.ID).
Str("module", "whitelist").
Msg("auth: access denied to new service users")
return ErrWhitelist
}
if !exists {
if err := ac.createAccount(ctx); err != nil {
return err
}
return nil
}
if curAccount.TritonUUID != ac.TritonAccount.ID {
curAccount.TritonUUID = ac.TritonAccount.ID
if err := curAccount.Save(ctx); err != nil {
return errors.Wrapf(err, "failed to save %q account", curAccount.AccountName)
}
}
ac.Account = curAccount
log.Debug().
Str("account_id", ac.Account.ID).
Str("account_name", ac.Account.AccountName).
Str("triton_uuid", ac.Account.TritonUUID).
Msg("auth: found existing account in database")
return nil
}
// HasTritonAccount returns a boolean whether or not we've authenticated with Triton.
func (ac *AccountCheck) HasTritonAccount() bool {
return ac.TritonAccount != nil
}
// HasAccount returns a boolean whether or not the database has a valid Account.
func (ac *AccountCheck) HasAccount() bool {
return ac.Account != nil
}
func (ac *AccountCheck) IsAuthentic() bool {
return ac.HasTritonAccount() && ac.HasAccount()
}