-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
path_duo_access.go
119 lines (105 loc) · 3.02 KB
/
path_duo_access.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
package duo
import (
"context"
"fmt"
"net/url"
duoapi "github.com/duosecurity/duo_api_golang"
"github.com/duosecurity/duo_api_golang/authapi"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
type AuthClient interface {
Preauth(options ...func(*url.Values)) (*authapi.PreauthResult, error)
Auth(factor string, options ...func(*url.Values)) (*authapi.AuthResult, error)
}
func pathDuoAccess() *framework.Path {
return &framework.Path{
Pattern: `duo/access`,
Fields: map[string]*framework.FieldSchema{
"skey": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Duo secret key",
},
"ikey": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Duo integration key",
},
"host": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Duo api host",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.UpdateOperation: pathDuoAccessWrite,
},
HelpSynopsis: pathDuoAccessHelpSyn,
HelpDescription: pathDuoAccessHelpDesc,
}
}
func GetDuoAuthClient(ctx context.Context, req *logical.Request, config *DuoConfig) (AuthClient, error) {
entry, err := req.Storage.Get(ctx, "duo/access")
if err != nil {
return nil, err
}
if entry == nil {
return nil, fmt.Errorf(
"Duo access credentials haven't been configured. Please configure\n" +
"them at the 'duo/access' endpoint")
}
var access DuoAccess
if err := entry.DecodeJSON(&access); err != nil {
return nil, err
}
duoClient := duoapi.NewDuoApi(
access.IKey,
access.SKey,
access.Host,
config.UserAgent,
)
duoAuthClient := authapi.NewAuthApi(*duoClient)
check, err := duoAuthClient.Check()
if err != nil {
return nil, err
}
if check == nil {
return nil, fmt.Errorf("could not connect to Duo; got nil result back from API check call")
}
var msg, detail string
if check.StatResult.Message != nil {
msg = *check.StatResult.Message
}
if check.StatResult.Message_Detail != nil {
detail = *check.StatResult.Message_Detail
}
if check.StatResult.Stat != "OK" {
return nil, fmt.Errorf("could not connect to Duo: %q (%q)", msg, detail)
}
return duoAuthClient, nil
}
func pathDuoAccessWrite(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
entry, err := logical.StorageEntryJSON("duo/access", DuoAccess{
SKey: d.Get("skey").(string),
IKey: d.Get("ikey").(string),
Host: d.Get("host").(string),
})
if err != nil {
return nil, err
}
if err := req.Storage.Put(ctx, entry); err != nil {
return nil, err
}
return nil, nil
}
type DuoAccess struct {
SKey string `json:"skey"`
IKey string `json:"ikey"`
Host string `json:"host"`
}
const pathDuoAccessHelpSyn = `
Configure the access keys and host for Duo API connections.
`
const pathDuoAccessHelpDesc = `
To authenticate users with Duo, the backend needs to know what host to connect to
and must authenticate with an integration key and secret key. This endpoint is used
to configure that information.
`