Skip to content

Commit c9376a0

Browse files
committed
revert rbac changes
1 parent 32ff000 commit c9376a0

File tree

4 files changed

+49
-55
lines changed

4 files changed

+49
-55
lines changed

coderd/database/dbauthz/dbauthz.go

Lines changed: 27 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -158,49 +158,34 @@ func ActorFromContext(ctx context.Context) (rbac.Subject, bool) {
158158
}
159159

160160
var (
161-
subjectProvisionerd = func(orgID uuid.UUID) rbac.Subject {
162-
sitePermissions := map[string][]policy.Action{
163-
// TODO: Add ProvisionerJob resource type.
164-
rbac.ResourceFile.Type: {policy.ActionRead},
165-
rbac.ResourceSystem.Type: {policy.WildcardSymbol},
166-
rbac.ResourceTemplate.Type: {policy.ActionRead, policy.ActionUpdate},
167-
// Unsure why provisionerd needs update and read personal
168-
rbac.ResourceUser.Type: {policy.ActionRead, policy.ActionReadPersonal, policy.ActionUpdatePersonal},
169-
rbac.ResourceWorkspaceDormant.Type: {policy.ActionDelete, policy.ActionRead, policy.ActionUpdate, policy.ActionWorkspaceStop},
170-
rbac.ResourceWorkspace.Type: {policy.ActionDelete, policy.ActionRead, policy.ActionUpdate, policy.ActionWorkspaceStart, policy.ActionWorkspaceStop},
171-
rbac.ResourceApiKey.Type: {policy.WildcardSymbol},
172-
// When org scoped provisioner credentials are implemented,
173-
// this can be reduced to read a specific org.
174-
rbac.ResourceOrganization.Type: {policy.ActionRead},
175-
rbac.ResourceGroup.Type: {policy.ActionRead},
176-
}
177-
orgPermissions := map[string][]rbac.Permission{}
178-
179-
if orgID != uuid.Nil {
180-
// replace site wide org permissions with org scoped permissions
181-
delete(sitePermissions, rbac.ResourceOrganization.Type)
182-
orgPermissions = map[string][]rbac.Permission{
183-
orgID.String(): rbac.Permissions(map[string][]policy.Action{
161+
subjectProvisionerd = rbac.Subject{
162+
FriendlyName: "Provisioner Daemon",
163+
ID: uuid.Nil.String(),
164+
Roles: rbac.Roles([]rbac.Role{
165+
{
166+
Identifier: rbac.RoleIdentifier{Name: "provisionerd"},
167+
DisplayName: "Provisioner Daemon",
168+
Site: rbac.Permissions(map[string][]policy.Action{
169+
// TODO: Add ProvisionerJob resource type.
170+
rbac.ResourceFile.Type: {policy.ActionRead},
171+
rbac.ResourceSystem.Type: {policy.WildcardSymbol},
172+
rbac.ResourceTemplate.Type: {policy.ActionRead, policy.ActionUpdate},
173+
// Unsure why provisionerd needs update and read personal
174+
rbac.ResourceUser.Type: {policy.ActionRead, policy.ActionReadPersonal, policy.ActionUpdatePersonal},
175+
rbac.ResourceWorkspaceDormant.Type: {policy.ActionDelete, policy.ActionRead, policy.ActionUpdate, policy.ActionWorkspaceStop},
176+
rbac.ResourceWorkspace.Type: {policy.ActionDelete, policy.ActionRead, policy.ActionUpdate, policy.ActionWorkspaceStart, policy.ActionWorkspaceStop},
177+
rbac.ResourceApiKey.Type: {policy.WildcardSymbol},
178+
// When org scoped provisioner credentials are implemented,
179+
// this can be reduced to read a specific org.
184180
rbac.ResourceOrganization.Type: {policy.ActionRead},
181+
rbac.ResourceGroup.Type: {policy.ActionRead},
185182
}),
186-
}
187-
}
188-
189-
return rbac.Subject{
190-
FriendlyName: "Provisioner Daemon",
191-
ID: uuid.Nil.String(),
192-
Roles: rbac.Roles([]rbac.Role{
193-
{
194-
Identifier: rbac.RoleIdentifier{Name: "provisionerd"},
195-
DisplayName: "Provisioner Daemon",
196-
Site: rbac.Permissions(sitePermissions),
197-
Org: orgPermissions,
198-
User: []rbac.Permission{},
199-
},
200-
}),
201-
Scope: rbac.ScopeAll,
202-
}.WithCachedASTValue()
203-
}
183+
Org: map[string][]rbac.Permission{},
184+
User: []rbac.Permission{},
185+
},
186+
}),
187+
Scope: rbac.ScopeAll,
188+
}.WithCachedASTValue()
204189

205190
subjectAutostart = rbac.Subject{
206191
FriendlyName: "Autostart",
@@ -277,13 +262,7 @@ var (
277262
// AsProvisionerd returns a context with an actor that has permissions required
278263
// for provisionerd to function.
279264
func AsProvisionerd(ctx context.Context) context.Context {
280-
return context.WithValue(ctx, authContextKey{}, subjectProvisionerd(uuid.Nil))
281-
}
282-
283-
// AsProvisionerd returns a context with an actor that has permissions required
284-
// for an org scoped provisionerd to function.
285-
func AsOrganizationProvisionerd(ctx context.Context, orgID uuid.UUID) context.Context {
286-
return context.WithValue(ctx, authContextKey{}, subjectProvisionerd(orgID))
265+
return context.WithValue(ctx, authContextKey{}, subjectProvisionerd)
287266
}
288267

289268
// AsAutostart returns a context with an actor that has permissions required

coderd/httpmw/provisionerdaemon.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,24 +95,33 @@ func ExtractProvisionerDaemonAuthenticated(opts ExtractProvisionerAuthConfig) fu
9595
return
9696
}
9797

98-
if subtle.ConstantTimeCompare(pk.HashedSecret, provisionerkey.HashSecret(keyValue)) != 1 {
98+
if provisionerkey.Compare(pk.HashedSecret, provisionerkey.HashSecret(keyValue)) {
9999
handleOptional(http.StatusUnauthorized, codersdk.Response{
100100
Message: "provisioner daemon key invalid",
101101
})
102102
return
103103
}
104104

105-
// The PSK does not indicate a specific provisioner daemon. So just
105+
// The provisioner key does not indicate a specific provisioner daemon. So just
106106
// store a boolean so the caller can check if the request is from an
107107
// authenticated provisioner daemon.
108108
ctx = context.WithValue(ctx, provisionerDaemonContextKey{}, true)
109+
// store key used to authenticate the request
110+
ctx = context.WithValue(ctx, provisionerKeyAuthContextKey{}, pk)
109111
// nolint:gocritic // Authenticating as a provisioner daemon.
110-
ctx = dbauthz.AsOrganizationProvisionerd(ctx, pk.OrganizationID)
112+
ctx = dbauthz.AsProvisionerd(ctx)
111113
next.ServeHTTP(w, r.WithContext(ctx))
112114
})
113115
}
114116
}
115117

118+
type provisionerKeyAuthContextKey struct{}
119+
120+
func ProvisionerKeyAuthOptional(r *http.Request) (database.ProvisionerKey, bool) {
121+
user, ok := r.Context().Value(provisionerKeyAuthContextKey{}).(database.ProvisionerKey)
122+
return user, ok
123+
}
124+
116125
func fallbackToPSK(ctx context.Context, psk string, next http.Handler, w http.ResponseWriter, r *http.Request, handleOptional func(code int, response codersdk.Response)) {
117126
token := r.Header.Get(codersdk.ProvisionerDaemonPSK)
118127
if subtle.ConstantTimeCompare([]byte(token), []byte(psk)) != 1 {

coderd/provisionerkey/provisionerkey.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package provisionerkey
22

33
import (
44
"crypto/sha256"
5+
"crypto/subtle"
56
"fmt"
67
"strings"
78

@@ -49,3 +50,7 @@ func HashSecret(secret string) []byte {
4950
h := sha256.Sum256([]byte(secret))
5051
return h[:]
5152
}
53+
54+
func Compare(a []byte, b []byte) bool {
55+
return subtle.ConstantTimeCompare(a, b) != 1
56+
}

enterprise/coderd/provisionerdaemons.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,11 @@ func (p *provisionerDaemonAuth) authorize(r *http.Request, orgID uuid.UUID, tags
108108
return nil, false
109109
}
110110

111-
// ensure provisioner daemon subject can read organization
112-
_, err := p.db.GetOrganizationByID(ctx, orgID)
113-
if err != nil {
114-
return nil, false
111+
pk, ok := httpmw.ProvisionerKeyAuthOptional(r)
112+
if ok {
113+
if orgID != pk.OrganizationID {
114+
return nil, false
115+
}
115116
}
116117

117118
// If using provisioner key / PSK auth, the daemon is, by definition, scoped to the organization.

0 commit comments

Comments
 (0)