At Sourcegraph, Entitle - Permission management is used for time bound access management to systems. Entitle has built-in integrations for GCP/AWS/Terraform Cloud/etc. To extend Entitle’s capabilities to support privileged access to our services (Dotcom Site-Admin, SSC Admin, Sourcegraph Analytics) SAMS implements Entitle’s REST API integration specification. This allows Sourcegraph teammates to request roles to access our services using their SAMS account for authentication.
Add the role to the SAMS-SDK roles
package. Convention for adding roles is to publicly declare the role so that it can easily be imported into your code.
Collect all roles into a []roleInfo
and add a new line appending your roles to the registeredRoles
slice. This is used by SAMS to populate Entitle.
The resourceType
in roleInfo
determines if the role applies service-wide or for individual resources owned by the service.
Service
e.g. Dotcom site admin uses a service level role. Enterprise portal customer admin uses a resource level role with the enterprise_subscription
resource type.
var (
// Dotcom site admin
RoleDotcomSiteAdmin = ToRole(services.Dotcom, "site_admin")
dotcomRoles = []roleInfo{
{
id: RoleDotcomSiteAdmin,
service: services.Dotcom,
resourceType: Service,
},
}
)
var (
// Enterprise Portal customer admin
RoleEnterprisePortalCustomerAdmin = ToRole(services.EnterprisePortal, "customer_admin")
enterprisePortalRoles = []roleInfo{
{
id: RoleEnterprisePortalCustomerAdmin,
service: services.EnterprisePortal,
resourceType: EnterpriseSubscription,
},
}
)
If your role is for a new service, you need to first add the service to the SAMS-SDK services
package.
Before using the SAMS SDK to query user roles or register role resources you must ensure your client has the necessary scopes:
sams::user.roles::read
sams::roles.resources::write
User roles are queryable using the SAMS SDK RPC GetUserRolesByID(ctx context.Context, userID, service string) ([]*clientsv1.Role, error)
.
Clients must iterate through the returned slice of roles to determine if the desired role is present:
message Role {
// The fully qualified role name e.g. `dotcom::site_admin`
string role_id = 1;
// The service the role is scoped to.
string service = 2;
// If the role applies to a resource this is the ID of the resource.
optional string resource_id = 3;
// If the role applies to a resource the is the ResourceType of the resource.
optional string resource_type = 4;
}
Changes of user roles are propagated via SAMS notifications distribution system. To be notified when a user role change event (grant/revoke) has occurred, follow the instructions to configure your service to listen for UserRolesUpdated
events.
Implement the UserRolesUpdatedData
handler. It is important to note that by design the notification does not include if the role was granted/revoked. It is necessary to query SAMS for the user's roles and check for presence/absence of roles relevant to your service. This prevents issues with out of order notification delivery:
type UserRolesUpdatedData struct {
// AccountID is the SAMS external ID of the user whose roles have been updated.
AccountID string `json:"account_id"`
// Service is the service that the user's roles have been updated in.
Service services.Service `json:"service"`
// RoleID is the role that has been updated.
RoleID roles.Role `json:"role"`
// ResourceID is the ID of the resource the role has been updated on,
// if applicable. When ResourceID is empty, the role is a service-level
// role that does not apply to a specific resource.
ResourceID string `json:"resource_id,omitempty"`
// ResourceType is the type of the resource the role has been updated on,
// if applicable. When ResourceType is empty, the role is a service-level
// role that does not apply to a specific resource.
ResourceType roles.ResourceType `json:"resource_type,omitempty"`
}