feat: add the concept of an instance owner (#23497)
* feat: Add the instance owner concept
* feat: improve handling of instance resource type
* fix: remove relic of cloud/oss split
* feat: Add an instance id. This gets set during onboarding and can be used to uniquely identify that instance.
* chore: Revert "feat: Add an instance id. This gets set during onboarding and can be used to uniquely identify that instance."
This reverts commit 6a712df61e
.
We decided to stick with the "singleton" 1 id for now, as there is not a clear need for unique identifiers.
pull/23597/head
parent
f0072ef230
commit
67ccbae8ff
85
authz.go
85
authz.go
|
@ -3,7 +3,6 @@ package influxdb
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
"github.com/influxdata/influxdb/v2/kit/platform"
|
"github.com/influxdata/influxdb/v2/kit/platform"
|
||||||
|
@ -143,6 +142,8 @@ const (
|
||||||
RemotesResourceType = ResourceType("remotes") // 20
|
RemotesResourceType = ResourceType("remotes") // 20
|
||||||
// ReplicationsResourceType gives permission to one or more replications.
|
// ReplicationsResourceType gives permission to one or more replications.
|
||||||
ReplicationsResourceType = ResourceType("replications") // 21
|
ReplicationsResourceType = ResourceType("replications") // 21
|
||||||
|
// InstanceResourceType is a special permission that allows ownership of the entire instance (creating orgs/operator tokens/etc)
|
||||||
|
InstanceResourceType = ResourceType("instance") // 22
|
||||||
)
|
)
|
||||||
|
|
||||||
// AllResourceTypes is the list of all known resource types.
|
// AllResourceTypes is the list of all known resource types.
|
||||||
|
@ -169,6 +170,7 @@ var AllResourceTypes = []ResourceType{
|
||||||
AnnotationsResourceType, // 19
|
AnnotationsResourceType, // 19
|
||||||
RemotesResourceType, // 20
|
RemotesResourceType, // 20
|
||||||
ReplicationsResourceType, // 21
|
ReplicationsResourceType, // 21
|
||||||
|
InstanceResourceType, // 22
|
||||||
// NOTE: when modifying this list, please update the swagger for components.schemas.Permission resource enum.
|
// NOTE: when modifying this list, please update the swagger for components.schemas.Permission resource enum.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,6 +204,7 @@ func (t ResourceType) Valid() (err error) {
|
||||||
case AnnotationsResourceType: // 19
|
case AnnotationsResourceType: // 19
|
||||||
case RemotesResourceType: // 20
|
case RemotesResourceType: // 20
|
||||||
case ReplicationsResourceType: // 21
|
case ReplicationsResourceType: // 21
|
||||||
|
case InstanceResourceType: // 22
|
||||||
default:
|
default:
|
||||||
err = ErrInvalidResourceType
|
err = ErrInvalidResourceType
|
||||||
}
|
}
|
||||||
|
@ -221,17 +224,8 @@ type Permission struct {
|
||||||
Resource Resource `json:"resource"`
|
Resource Resource `json:"resource"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var newMatchBehavior bool
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
_, newMatchBehavior = os.LookupEnv("MATCHER_BEHAVIOR")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Matches returns whether or not one permission matches the other.
|
// Matches returns whether or not one permission matches the other.
|
||||||
func (p Permission) Matches(perm Permission) bool {
|
func (p Permission) Matches(perm Permission) bool {
|
||||||
if newMatchBehavior {
|
|
||||||
return p.matchesV2(perm)
|
|
||||||
}
|
|
||||||
return p.matchesV1(perm)
|
return p.matchesV1(perm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,6 +234,10 @@ func (p Permission) matchesV1(perm Permission) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.Resource.Type == InstanceResourceType {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
if p.Resource.Type != perm.Resource.Type {
|
if p.Resource.Type != perm.Resource.Type {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -278,53 +276,6 @@ func (p Permission) matchesV1(perm Permission) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p Permission) matchesV2(perm Permission) bool {
|
|
||||||
if p.Action != perm.Action {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Resource.Type != perm.Resource.Type {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Resource.OrgID == nil && p.Resource.ID == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Resource.OrgID != nil && perm.Resource.OrgID != nil && p.Resource.ID != nil && perm.Resource.ID != nil {
|
|
||||||
if *p.Resource.OrgID != *perm.Resource.OrgID && *p.Resource.ID == *perm.Resource.ID {
|
|
||||||
fmt.Printf("v2: old match used: p.Resource.OrgID=%s perm.Resource.OrgID=%s p.Resource.ID=%s",
|
|
||||||
*p.Resource.OrgID, *perm.Resource.OrgID, *p.Resource.ID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Resource.OrgID != nil {
|
|
||||||
if perm.Resource.OrgID != nil {
|
|
||||||
if *p.Resource.OrgID == *perm.Resource.OrgID {
|
|
||||||
if p.Resource.ID == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if perm.Resource.ID != nil {
|
|
||||||
return *p.Resource.ID == *perm.Resource.ID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.Resource.ID != nil {
|
|
||||||
pID := *p.Resource.ID
|
|
||||||
if perm.Resource.ID != nil {
|
|
||||||
permID := *perm.Resource.ID
|
|
||||||
if pID == permID {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p Permission) String() string {
|
func (p Permission) String() string {
|
||||||
return fmt.Sprintf("%s:%s", p.Action, p.Resource)
|
return fmt.Sprintf("%s:%s", p.Action, p.Resource)
|
||||||
}
|
}
|
||||||
|
@ -421,6 +372,11 @@ func NewPermissionAtID(id platform.ID, a Action, rt ResourceType, orgID platform
|
||||||
func OperPermissions() []Permission {
|
func OperPermissions() []Permission {
|
||||||
ps := []Permission{}
|
ps := []Permission{}
|
||||||
for _, r := range AllResourceTypes {
|
for _, r := range AllResourceTypes {
|
||||||
|
// For now, we are only allowing instance permissions when logged in through session auth
|
||||||
|
// That is handled in user resource mapping
|
||||||
|
if r == InstanceResourceType {
|
||||||
|
continue
|
||||||
|
}
|
||||||
for _, a := range actions {
|
for _, a := range actions {
|
||||||
ps = append(ps, Permission{Action: a, Resource: Resource{Type: r}})
|
ps = append(ps, Permission{Action: a, Resource: Resource{Type: r}})
|
||||||
}
|
}
|
||||||
|
@ -434,6 +390,11 @@ func OperPermissions() []Permission {
|
||||||
func ReadAllPermissions() []Permission {
|
func ReadAllPermissions() []Permission {
|
||||||
ps := make([]Permission, len(AllResourceTypes))
|
ps := make([]Permission, len(AllResourceTypes))
|
||||||
for i, t := range AllResourceTypes {
|
for i, t := range AllResourceTypes {
|
||||||
|
// For now, we are only allowing instance permissions when logged in through session auth
|
||||||
|
// That is handled in user resource mapping
|
||||||
|
if t == InstanceResourceType {
|
||||||
|
continue
|
||||||
|
}
|
||||||
ps[i] = Permission{Action: ReadAction, Resource: Resource{Type: t}}
|
ps[i] = Permission{Action: ReadAction, Resource: Resource{Type: t}}
|
||||||
}
|
}
|
||||||
return ps
|
return ps
|
||||||
|
@ -443,6 +404,11 @@ func ReadAllPermissions() []Permission {
|
||||||
func OwnerPermissions(orgID platform.ID) []Permission {
|
func OwnerPermissions(orgID platform.ID) []Permission {
|
||||||
ps := []Permission{}
|
ps := []Permission{}
|
||||||
for _, r := range AllResourceTypes {
|
for _, r := range AllResourceTypes {
|
||||||
|
// For now, we are only allowing instance permissions when logged in through session auth
|
||||||
|
// That is handled in user resource mapping
|
||||||
|
if r == InstanceResourceType {
|
||||||
|
continue
|
||||||
|
}
|
||||||
for _, a := range actions {
|
for _, a := range actions {
|
||||||
if r == OrgsResourceType {
|
if r == OrgsResourceType {
|
||||||
ps = append(ps, Permission{Action: a, Resource: Resource{Type: r, ID: &orgID}})
|
ps = append(ps, Permission{Action: a, Resource: Resource{Type: r, ID: &orgID}})
|
||||||
|
@ -468,6 +434,11 @@ func MePermissions(userID platform.ID) []Permission {
|
||||||
func MemberPermissions(orgID platform.ID) []Permission {
|
func MemberPermissions(orgID platform.ID) []Permission {
|
||||||
ps := []Permission{}
|
ps := []Permission{}
|
||||||
for _, r := range AllResourceTypes {
|
for _, r := range AllResourceTypes {
|
||||||
|
// For now, we are only allowing instance permissions when logged in through session auth
|
||||||
|
// That is handled in user resource mapping
|
||||||
|
if r == InstanceResourceType {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if r == OrgsResourceType {
|
if r == OrgsResourceType {
|
||||||
ps = append(ps, Permission{Action: ReadAction, Resource: Resource{Type: r, ID: &orgID}})
|
ps = append(ps, Permission{Action: ReadAction, Resource: Resource{Type: r, ID: &orgID}})
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -45,6 +45,7 @@ func TestResourceListHandler(t *testing.T) {
|
||||||
string(influxdb.AnnotationsResourceType),
|
string(influxdb.AnnotationsResourceType),
|
||||||
string(influxdb.RemotesResourceType),
|
string(influxdb.RemotesResourceType),
|
||||||
string(influxdb.ReplicationsResourceType),
|
string(influxdb.ReplicationsResourceType),
|
||||||
|
string(influxdb.InstanceResourceType),
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := w.Result()
|
resp := w.Result()
|
||||||
|
|
|
@ -152,6 +152,16 @@ func (s *OnboardService) onboardUser(ctx context.Context, req *influxdb.Onboardi
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := s.service.CreateUserResourceMapping(ctx, &influxdb.UserResourceMapping{
|
||||||
|
UserID: user.ID,
|
||||||
|
UserType: influxdb.Owner,
|
||||||
|
MappingType: influxdb.UserMappingType,
|
||||||
|
ResourceType: influxdb.InstanceResourceType,
|
||||||
|
ResourceID: platform.ID(1), // The instance doesn't have a resourceid
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// create orgs buckets
|
// create orgs buckets
|
||||||
ub := &influxdb.Bucket{
|
ub := &influxdb.Bucket{
|
||||||
OrgID: org.ID,
|
OrgID: org.ID,
|
||||||
|
|
|
@ -149,6 +149,13 @@ func (m *UserResourceMapping) ownerPerms() ([]Permission, error) {
|
||||||
return OwnerPermissions(m.ResourceID), nil
|
return OwnerPermissions(m.ResourceID), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.ResourceType == InstanceResourceType {
|
||||||
|
return []Permission{
|
||||||
|
{Action: ReadAction, Resource: Resource{Type: InstanceResourceType}},
|
||||||
|
{Action: WriteAction, Resource: Resource{Type: InstanceResourceType}},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
ps := []Permission{
|
ps := []Permission{
|
||||||
// TODO: Uncomment these once the URM system is no longer being used for find lookups for:
|
// TODO: Uncomment these once the URM system is no longer being used for find lookups for:
|
||||||
// Telegraf
|
// Telegraf
|
||||||
|
|
Loading…
Reference in New Issue