feat/sg: add 'sg sams' commands 'create-client-token' and 'introspect-token'#62883
feat/sg: add 'sg sams' commands 'create-client-token' and 'introspect-token'#62883
Conversation
There was a problem hiding this comment.
We previously talked about making a SAMS-specific CLI, but IMO that's a pretty big pain point if we want SAMS integration adoption when everything else lives in sg, and all the nice tooling lives here as well.
Directionally, this sounds like the right call. (Though I still liked the idea of a Sam Adams 🍺 sams-admin tool 😢.)
In case it helps, these are the things that I've needed to do as an admin of a SAMS integration:
CRUD on the scopes that a SAMS client can send in a request. (e.g. authorize "my app" to send tokens with "your app"'s permissions.) It seems like we'd need to be careful about how we expose that type of functionality though. (e.g. requiring that only an admin of "your app" can update "my app" to issue scopes for "your app", etc.)
| return errors.Wrap(err, "generate token") | ||
| } | ||
|
|
||
| data, err := json.MarshalIndent(token, "", " ") |
There was a problem hiding this comment.
Not to over-think it, but it would be nice to separate concerns from "CLI tooling stuff" from "SAMS client interactions"?
e.g. within this file, maybe have a:
// samsClientAdmin is an API client for interacting with
// the SAMS APIs on behalf of a SAMS client, e.g. an OAuth
// app that _uses_ SAMS.
type samsClientAdmin struct {
TokenSource ouath.TokenSource
}
// GetClientToken returns the current OAuth access token generated from
// the underlying token source.
func (sac *samsAdminClient) GetClientToken() string { ... }
// And later...
func (sac *samsAdminClient) ListScopes() ([]sdk.Scope, error) { ... }
func (sac *samsAdminClient) AddScopeToApp(newScope sdk.Scope) error { ... }There was a problem hiding this comment.
Hmm, I'm inclined to keep this as is for now - I don't think this makes the callsite here much simpler (e.g. I don't think this client type should handle JSON marshalling, so the callsite still needs to handle the get-token error and then the JSON marshalling), and in between the other client types (oauth2.TokenSource is arguably a client type, as the .Token() gives us a structured type and whatnot with the credentials, as well as the existing sams.ClientV1) we already have a lot of logic that is separated from the CLI tooling stuff.
There was a problem hiding this comment.
In other words, what we have here is basically already all CLI concerns (constructing type from flag, doing the thing, checking the error, dumping the output appropriately)
It does help; I'd love to expand on the tooling here for all your SAMS-integration-development needs 😁 once @unknwon gets the chance to review, I'll open some tickets tracking some follow-up ideas |
…ess (#62771) This PR exposes the data layer implemented in https://github.com/sourcegraph/sourcegraph/pull/62706 via the Enterprise Portal API. We register the services proposed in #62263 and also set up tooling like gRPC UI locally for DX. Auth is via SAMS M2M; sourcegraph/sourcegraph-accounts-sdk-go#28 and sourcegraph/sourcegraph-accounts#227 rolls out the new scopes, and sourcegraph/managed-services#1474 adds credentials for the enterprise-portal-dev deployment. Closes CORE-112 ## Test plan https://github.com/sourcegraph/sourcegraph/pull/62706 has extensive testing of the data layer, and this PR expands on it a little bit. I tested the RPC layer by hand: Create SAMS client for Enterprise Portal Dev in **accounts.sgdev.org**: ```sh curl -s -X POST \ -H "Authorization: Bearer $MANAGEMENT_SECRET" \ https://accounts.sgdev.org/api/management/v1/identity-provider/clients \ --data '{"name": "enterprise-portal-dev", "scopes": [], "redirect_uris": ["https://enterprise-portal.sgdev.org"]}' | jq ``` Configure `sg.config.overwrite.yaml` ```yaml enterprise-portal: env: SRC_LOG_LEVEL: debug # sams-dev SAMS_URL: https://accounts.sgdev.org ENTERPRISE_PORTAL_SAMS_CLIENT_ID: "sams_cid_..." ENTERPRISE_PORTAL_SAMS_CLIENT_SECRET: "sams_cs_..." ``` Create a test client (later, we will do the same thing for Cody Gateway), also in **accounts.sgdev.org**: ```sh curl -s -X POST \ -H "Authorization: Bearer $MANAGEMENT_SECRET" \ https://accounts.sgdev.org/api/management/v1/identity-provider/clients \ --data '{"name": "enterprise-portal-dev-reader", "scopes": ["enterprise_portal::codyaccess::read", "enterprise_portal::subscription::read"], "redirect_uris": ["https://enterprise-portal.sgdev.org"]}' | jq ``` Then: ``` sg run enterprise-portal ``` Navigate to the locally-enabled gRPC debug UI at http://localhost:6081/debug/grcpui, using https://github.com/sourcegraph/sourcegraph/pull/62883 to get an access token from our test client to add in the request metadata: ```sh sg sams create-client-token -s 'enterprise_portal::codyaccess::read' ``` I'm using some local subscriptions I've made previously in `sg start dotcom`:   Without a valid authorization header:  Verified a lookup using the returned access tokens also works --------- Co-authored-by: Jean-Hadrien Chabran <jh@chabran.fr> Co-authored-by: Joe Chen <joe@sourcegraph.com>
The direction sounds good, tho I'd want SAMS to first stop using shared-static management secret, e.g. somehow supporting/take advantage of (validating) credentials produced by |
Co-authored-by: Joe Chen <joe@sourcegraph.com>
Right now, developing SAMS clients involves raw cURL commands (see operator cheat sheet) (which is fine), but other steps like "testing auth" require using accounts-clients-example, which isn't very well documented and requires a bit of hand-wringing to get to and start using.
We previously talked about making a SAMS-specific CLI, but IMO that's a pretty big pain point if we want SAMS integration adoption when everything else lives in
sg, and all the nice tooling lives here as well.This PR migrates the next steps after using cURL to set up clients (
create-client-tokenandintrospect-token) from accounts-clients-example to a newsg samstoolchain for better DX (docs, completions, flags)Test plan