This repository has been archived by the owner on Dec 31, 2022. It is now read-only.
/
backend.go
226 lines (180 loc) · 6.51 KB
/
backend.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
package slack
import (
"context"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
"github.com/pkg/errors"
)
// Factory creates a new usable instance of this auth method.
func Factory(ctx context.Context, c *logical.BackendConfig) (logical.Backend, error) {
b := Backend(c)
if err := b.Setup(ctx, c); err != nil {
return nil, errors.Wrapf(err, "failed to create factory")
}
return b, nil
}
// backend is the actual backend
type backend struct {
*framework.Backend
GroupsMap *framework.PolicyMap
UsergroupsMap *framework.PolicyMap
UsersMap *framework.PolicyMap
}
// Backend creates a new backend, mapping the proper paths, help information,
// and required callbacks.
func Backend(c *logical.BackendConfig) *backend {
var b backend
// GroupsMap maps private channels (like #team-ops) to a series of policies.
b.GroupsMap = &framework.PolicyMap{
PathMap: framework.PathMap{
Name: "groups",
},
PolicyKey: "policy",
}
// UsergroupsMap maps usergroups (like @marketing) to a series of policies.
b.UsergroupsMap = &framework.PolicyMap{
PathMap: framework.PathMap{
Name: "usergroups",
},
PolicyKey: "policy",
}
// UsersMap maps a slack username to a series of policies.
b.UsersMap = &framework.PolicyMap{
PathMap: framework.PathMap{
Name: "users",
},
PolicyKey: "policy",
}
b.Backend = &framework.Backend{
BackendType: logical.TypeCredential,
AuthRenew: b.pathAuthRenew,
Help: backendHelp,
PathsSpecial: &logical.Paths{
Unauthenticated: []string{"login/*"},
},
Paths: func() []*framework.Path {
var paths []*framework.Path
// auth/slack/info
paths = append(paths, &framework.Path{
Pattern: "info",
HelpSynopsis: "Display information about the plugin",
HelpDescription: `
Displays information about the plugin, such as the plugin version and where to
get help.
`,
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.ReadOperation: b.pathInfoRead,
},
})
// auth/slack/map/groups/*
paths = append(paths, b.GroupsMap.Paths()...)
// auth/slack/map/usergroups/*
paths = append(paths, b.UsergroupsMap.Paths()...)
// auth/slack/map/users/*
paths = append(paths, b.UsersMap.Paths()...)
// auth/slack/config
paths = append(paths, &framework.Path{
Pattern: "config",
HelpSynopsis: "Configuration such the team and ttls",
HelpDescription: `
Read or writer configuration to Vault's storage backend such as OAuth
information, team, behavior configuration tunables, and TTLs. For example:
$ vault write auth/slack/config \
access_token="xoxp-2164918114..." \
teams="HashiCorp"
For more information and examples, please see the online documentation.
`,
Fields: map[string]*framework.FieldSchema{
"access_token": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Slack OAuth access token for your Slack application.",
},
"teams": &framework.FieldSchema{
Type: framework.TypeCommaStringSlice,
Description: "Comma-separated list of permitted Slack teams. The " +
"user must be a member of at least one of these teams to " +
"authenticate.",
},
"allow_bot_users": &framework.FieldSchema{
Type: framework.TypeBool,
Description: "Allow bot users to authenticate.",
},
"allow_non_2fa": &framework.FieldSchema{
Type: framework.TypeBool,
Description: "Allow users to not have 2FA enabled on their Slack " +
"account to authenticate.",
Default: true,
},
"allow_restricted_users": &framework.FieldSchema{
Type: framework.TypeBool,
Description: "Allow restricted users (multi-channel guests) to " +
"authenticate.",
},
"allow_ultra_restricted_users": &framework.FieldSchema{
Type: framework.TypeBool,
Description: "Allow ultra restricted users (single-channel " +
"guests) to authenticate.",
},
"anyone_policies": &framework.FieldSchema{
Type: framework.TypeCommaStringSlice,
Description: "Comma-separated list of policies to apply to " +
"everyone, even unmapped users.",
},
"ttl": &framework.FieldSchema{
Type: framework.TypeDurationSecond,
Description: "Duration after which authentication will expire.",
},
"max_ttl": &framework.FieldSchema{
Type: framework.TypeDurationSecond,
Description: "Maximum duration after which authentication will expire.",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.UpdateOperation: b.pathConfigWrite,
logical.ReadOperation: b.pathConfigRead,
},
})
// auth/slack/login/token
paths = append(paths, &framework.Path{
Pattern: "login/token",
HelpSynopsis: "Authenticate using a personal OAuth token",
HelpDescription: `
Accepts a user's Slack personal OAuth token and performs a lookup on that user's
token to verify identity, group membership, etc. This identity information is
then used to map the user to policies in Vault.
`,
Fields: map[string]*framework.FieldSchema{
"token": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Slack personal OAuth token to use for " +
"authentication. Get your personal access token in your Slack " +
"account settings.",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
logical.UpdateOperation: b.pathAuthLogin,
},
})
return paths
}(),
}
return &b
}
const backendHelp = `
The Slack auth method authenticates users using Slack groups, usergroups, or
user ID maps.
Users are automatically authenticated through a Slack team through the Slack
API. For example:
* Allow anyone in the Slack team "hashicorp" in the private group "#ops"
to authenticate to Vault and receive a token with the policy "operator".
* Allow anyone in the Slack team "hashicorp" in the user group "@oncall"
to authenticate to Vault and receive a token with the policy "enoc".
* Allow the user "sethvargo" in the Slack team "hashicorp" to receive a
root token.
Slack sometimes refers to teams as "workspaces". It is confusing. We are sorry.
Additionally, humans tend to think of slack groups and users as their
"display name" (e.g. @marketing), but Slack strongly recommends API clients use
IDs. For convenience, this auth method automatically maps those display names
to IDs at configuration time. As such, if you rename a group or user, they will
still continue to receive the same permissions.
`