sourcegraph/lib/managedservicesplatform/iam/iam.go
Joe Chen b717fd518a
enterprise-portal: implement basic MSP IAM and RPCs (#63173)
Closes CORE-99, closes CORE-176

This PR is based off (and was also served as PoC of) [RFC 962: MSP IAM
framework](https://docs.google.com/document/d/1ItJlQnpR5AHbrfAholZqjH8-8dPF1iQcKh99gE6SSjs/edit).
It comes with two main parts:

1. The initial version of the MSP IAM SDK:
`lib/managedservicesplatform/iam`
- Embeds the [OpenFGA server
implementation](https://github.com/openfga/openfga/tree/main/pkg/server)
and exposes the a `ClientV1` for interacting with it.
- Automagically manages the both MSP IAM's and OpenFGA's database
migrations upon initializing the `ClientV1`.
![CleanShot 2024-06-18 at 15 09
24@2x](https://github.com/sourcegraph/sourcegraph/assets/2946214/387e0e28-a6c2-4664-b946-0ea4a1dd0804)
- Ensures the specified OpenFGA's store and automatization model DSL
exists.
- Utility types and helpers to avoid easy mistakes (i.e. make the
relation tuples a bit more strongly-typed).
- Decided to put all types and pre-defined values together to simulate a
"central registry" and acting as a forcing function for services to form
some sort of convention. Then when we migrate the OpenFGA server to a
separate standalone service, it will be less headache about
consolidating similar meaning types/relations but different string
literals.
1. The first use case of the MSP IAM:
`cmd/enterprise-portal/internal/subscriptionsservice`
	- Added/updated RPCs:
		- Listing enterprise subscriptions via permissions
		- Update enterprise subscriptions to assign instance domains
- Update enterprise subscriptions membership to assign roles (and
permissions)
- A database table for enterprise subscriptions, only storing the extra
instance domains as Enterprise Portal is not the
writeable-source-of-truth.

## Other minor changes

- Moved `internal/redislock` to `lib/redislock` to be used in MSP IAM
SDK.
- Call `createdb ...` as part of `enterprise-portal` install script in
`sg.config.yaml` (`msp_iam` database is a hard requirement of MSP IAM
framework).

## Test plan

Tested with gRPC UI:

- `UpdateEnterpriseSubscription` to assign an instance domain
- `UpdateEnterpriseSubscriptionMembership` to assign roles
- `ListEnterpriseSubscriptions`:
	- List by subscription ID
	- List by instance domain
	- List by view cody analytics permissions

---------

Co-authored-by: Robert Lin <robert@bobheadxi.dev>
2024-06-19 21:46:48 -04:00

48 lines
1.3 KiB
Go

package iam
import (
"fmt"
)
type TupleType string
// Resource types.
const (
TupleTypeSubscriptionCodyAnalytics TupleType = "subscription_cody_analytics"
)
// Role objects.
const (
TupleTypeCustomerAdmin TupleType = "customer_admin"
TupleTypeUser TupleType = "user"
)
type TupleObject string
// ToTupleObject creates a TupleObject from the given type and ID, e.g.
// "subscription_cody_analytics:80ca12e2-54b4-448c-a61a-390b1a9c1224".
func ToTupleObject(typ TupleType, id string) TupleObject {
return TupleObject(fmt.Sprintf("%s:%s", typ, id))
}
type TupleRelation string
const (
TupleRelationMember TupleRelation = "member"
TupleRelationView TupleRelation = "view"
)
type TupleSubject string
// ToTupleSubjectUser creates a TupleSubject from a SAMS account ID for users,
// e.g. "user:018d21f2-04a6-7aaf-9f6f-6fc58c4187b9".
func ToTupleSubjectUser(samsAccountID string) TupleSubject {
return TupleSubject(fmt.Sprintf("%s:%s", TupleTypeUser, samsAccountID))
}
// ToTupleSubjectCustomerAdmin creates a TupleSubject from the given ID and
// relation customer admins, e.g. "customer_admin:80ca12e2-54b4-448c-a61a-390b1a9c1224#member".
func ToTupleSubjectCustomerAdmin(id string, relation TupleRelation) TupleSubject {
return TupleSubject(fmt.Sprintf("%s:%s#%s", TupleTypeCustomerAdmin, id, relation))
}