mirror of
https://github.com/grafana/grafana.git
synced 2025-08-02 11:31:35 +08:00

* Moving POC files from #64283 to a new branch Co-authored-by: Mihály Gyöngyösi <mgyongyosi@users.noreply.github.com> * Adding missing permission definition Co-authored-by: Mihály Gyöngyösi <mgyongyosi@users.noreply.github.com> * Force the service instantiation while client isn't merged Co-authored-by: Mihály Gyöngyösi <mgyongyosi@users.noreply.github.com> * Merge conf with main Co-authored-by: Mihály Gyöngyösi <mgyongyosi@users.noreply.github.com> * Leave go-sqlite3 version unchanged Co-authored-by: Mihály Gyöngyösi <mgyongyosi@users.noreply.github.com> * tidy Co-authored-by: Mihály Gyöngyösi <mgyongyosi@users.noreply.github.com> * User SearchUserPermissions instead of SearchUsersPermissions * Replace DummyKeyService with signingkeys.Service * Use user🆔<id> as subject * Fix introspection endpoint issue * Add X-Grafana-Org-Id to get_resources.bash script * Regenerate toggles_gen.go * Fix basic.go * Add GetExternalService tests * Add GetPublicKeyScopes tests * Add GetScopesOnUser tests * Add GetScopes tests * Add ParsePublicKeyPem tests * Add database test for GetByName * re-add comments * client tests added * Add GetExternalServicePublicKey tests * Add other test case to GetExternalServicePublicKey * client_credentials grant test * Add test to jwtbearer grant * Test Comments * Add handleKeyOptions tests * Add RSA key generation test * Add ECDSA by default to EmbeddedSigningKeysService * Clean up org id scope and audiences * Add audiences to the DB * Fix check on Audience * Fix double import * Add AC Store mock and align oauthserver tests * Fix test after rebase * Adding missing store function to mock * Fix double import * Add CODEOWNER * Fix some linting errors * errors don't need type assertion * Typo codeowners * use mockery for oauthserver store * Add feature toggle check * Fix db tests to handle the feature flag * Adding call to DeleteExternalServiceRole * Fix flaky test * Re-organize routes comments and plan futur work * Add client_id check to Extended JWT client * Clean up * Fix * Remove background service registry instantiation of the OAuth server * Comment cleanup * Remove unused client function * Update go.mod to use the latest ory/fosite commit * Remove oauth2_server related configs from defaults.ini * Add audiences to DTO * Fix flaky test * Remove registration endpoint and demo scripts. Document code * Rename packages * Remove the OAuthService vs OAuthServer confusion * fix incorrect import ext_jwt_test * Comments and order * Comment basic auth * Remove unecessary todo * Clean api * Moving ParsePublicKeyPem to utils * re ordering functions in service.go * Fix comment * comment on the redirect uri * Add RBAC actions, not only scopes * Fix tests * re-import featuremgmt in migrations * Fix wire * Fix scopes in test * Fix flaky test * Remove todo, the intersection should always return the minimal set * Remove unecessary check from intersection code * Allow env overrides on settings * remove the term app name * Remove app keyword for client instead and use Name instead of ExternalServiceName * LogID remove ExternalService ref * Use Name instead of ExternalServiceName * Imports order * Inline * Using ExternalService and ExternalServiceDTO * Remove xorm tags * comment * Rename client files * client -> external service * comments * Move test to correct package * slimmer test * cachedUser -> cachedExternalService * Fix aggregate store test * PluginAuthSession -> AuthSession * Revert the nil cehcks * Remove unecessary extra * Removing custom session * fix typo in test * Use constants for tests * Simplify HandleToken tests * Refactor the HandleTokenRequest test * test message * Review test * Prevent flacky test on client as well * go imports * Revert changes from 526e48ad4550fed7e2b753b9d0a0cc6097155f58 * AuthN: Change the External Service registration form (#68649) * AuthN: change the External Service registration form * Gen default permissions * Change demo script registration form * Remove unecessary comment * Nit. * Reduce cyclomatic complexity * Remove demo_scripts * Handle case with no service account * Comments * Group key gen * Nit. * Check the SaveExternalService test * Rename cachedUser to cachedClient in test * One more test case to database test * Comments * Remove last org scope Co-authored-by: Mihály Gyöngyösi <mgyongyosi@users.noreply.github.com> * Update pkg/services/oauthserver/utils/utils_test.go * Update pkg/services/sqlstore/migrations/oauthserver/migrations.go Remove comment * Update pkg/setting/setting.go Co-authored-by: Gabriel MABILLE <gamab@users.noreply.github.com> --------- Co-authored-by: Mihály Gyöngyösi <mgyongyosi@users.noreply.github.com>
162 lines
5.1 KiB
Go
162 lines
5.1 KiB
Go
package oauthserver
|
|
|
|
import (
|
|
"context"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/ory/fosite"
|
|
|
|
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
|
"github.com/grafana/grafana/pkg/services/user"
|
|
)
|
|
|
|
type KeyResult struct {
|
|
URL string `json:"url,omitempty"`
|
|
PrivatePem string `json:"private,omitempty"`
|
|
PublicPem string `json:"public,omitempty"`
|
|
Generated bool `json:"generated,omitempty"`
|
|
}
|
|
|
|
type ExternalServiceDTO struct {
|
|
Name string `json:"name"`
|
|
ID string `json:"clientId"`
|
|
Secret string `json:"clientSecret"`
|
|
RedirectURI string `json:"redirectUri,omitempty"` // Not used yet (code flow)
|
|
GrantTypes string `json:"grantTypes"` // CSV value
|
|
Audiences string `json:"audiences"` // CSV value
|
|
KeyResult *KeyResult `json:"key,omitempty"`
|
|
}
|
|
|
|
type ExternalService struct {
|
|
ID int64 `xorm:"id pk autoincr"`
|
|
Name string `xorm:"name"`
|
|
ClientID string `xorm:"client_id"`
|
|
Secret string `xorm:"secret"`
|
|
RedirectURI string `xorm:"redirect_uri"` // Not used yet (code flow)
|
|
GrantTypes string `xorm:"grant_types"` // CSV value
|
|
Audiences string `xorm:"audiences"` // CSV value
|
|
PublicPem []byte `xorm:"public_pem"`
|
|
ServiceAccountID int64 `xorm:"service_account_id"`
|
|
// SelfPermissions are the registered service account permissions (registered and managed permissions)
|
|
SelfPermissions []ac.Permission
|
|
// ImpersonatePermissions is the restriction set of permissions while impersonating
|
|
ImpersonatePermissions []ac.Permission
|
|
|
|
// SignedInUser refers to the current Service Account identity/user
|
|
SignedInUser *user.SignedInUser
|
|
Scopes []string
|
|
ImpersonateScopes []string
|
|
}
|
|
|
|
func (c *ExternalService) ToDTO() *ExternalServiceDTO {
|
|
c2 := ExternalServiceDTO{
|
|
Name: c.Name,
|
|
ID: c.ClientID,
|
|
Secret: c.Secret,
|
|
GrantTypes: c.GrantTypes,
|
|
Audiences: c.Audiences,
|
|
RedirectURI: c.RedirectURI,
|
|
}
|
|
if len(c.PublicPem) > 0 {
|
|
c2.KeyResult = &KeyResult{PublicPem: string(c.PublicPem)}
|
|
}
|
|
return &c2
|
|
}
|
|
|
|
func (c *ExternalService) LogID() string {
|
|
return "{name: " + c.Name + ", clientID: " + c.ClientID + "}"
|
|
}
|
|
|
|
// GetID returns the client ID.
|
|
func (c *ExternalService) GetID() string { return c.ClientID }
|
|
|
|
// GetHashedSecret returns the hashed secret as it is stored in the store.
|
|
func (c *ExternalService) GetHashedSecret() []byte {
|
|
// Hashed version is stored in the secret field
|
|
return []byte(c.Secret)
|
|
}
|
|
|
|
// GetRedirectURIs returns the client's allowed redirect URIs.
|
|
func (c *ExternalService) GetRedirectURIs() []string {
|
|
return []string{c.RedirectURI}
|
|
}
|
|
|
|
// GetGrantTypes returns the client's allowed grant types.
|
|
func (c *ExternalService) GetGrantTypes() fosite.Arguments {
|
|
return strings.Split(c.GrantTypes, ",")
|
|
}
|
|
|
|
// GetResponseTypes returns the client's allowed response types.
|
|
// All allowed combinations of response types have to be listed, each combination having
|
|
// response types of the combination separated by a space.
|
|
func (c *ExternalService) GetResponseTypes() fosite.Arguments {
|
|
return fosite.Arguments{"code"}
|
|
}
|
|
|
|
// GetScopes returns the scopes this client is allowed to request on its own behalf.
|
|
func (c *ExternalService) GetScopes() fosite.Arguments {
|
|
if c.Scopes != nil {
|
|
return c.Scopes
|
|
}
|
|
|
|
ret := []string{"profile", "email", "groups", "entitlements"}
|
|
if c.SignedInUser != nil && c.SignedInUser.Permissions != nil {
|
|
perms := c.SignedInUser.Permissions[TmpOrgID]
|
|
for action := range perms {
|
|
// Add all actions that the plugin is allowed to request
|
|
ret = append(ret, action)
|
|
}
|
|
}
|
|
|
|
c.Scopes = ret
|
|
return ret
|
|
}
|
|
|
|
// GetScopes returns the scopes this client is allowed to request on a specific user.
|
|
func (c *ExternalService) GetScopesOnUser(ctx context.Context, accessControl ac.AccessControl, userID int64) []string {
|
|
ev := ac.EvalPermission(ac.ActionUsersImpersonate, ac.Scope("users", "id", strconv.FormatInt(userID, 10)))
|
|
hasAccess, errAccess := accessControl.Evaluate(ctx, c.SignedInUser, ev)
|
|
if errAccess != nil || !hasAccess {
|
|
return nil
|
|
}
|
|
|
|
if c.ImpersonateScopes != nil {
|
|
return c.ImpersonateScopes
|
|
}
|
|
|
|
ret := []string{}
|
|
if c.ImpersonatePermissions != nil {
|
|
perms := c.ImpersonatePermissions
|
|
for i := range perms {
|
|
if perms[i].Action == ac.ActionUsersRead && perms[i].Scope == ScopeGlobalUsersSelf {
|
|
ret = append(ret, "profile", "email", ac.ActionUsersRead)
|
|
continue
|
|
}
|
|
if perms[i].Action == ac.ActionUsersPermissionsRead && perms[i].Scope == ScopeUsersSelf {
|
|
ret = append(ret, "entitlements", ac.ActionUsersPermissionsRead)
|
|
continue
|
|
}
|
|
if perms[i].Action == ac.ActionTeamsRead && perms[i].Scope == ScopeTeamsSelf {
|
|
ret = append(ret, "groups", ac.ActionTeamsRead)
|
|
continue
|
|
}
|
|
// Add all actions that the plugin is allowed to request
|
|
ret = append(ret, perms[i].Action)
|
|
}
|
|
}
|
|
|
|
c.ImpersonateScopes = ret
|
|
return ret
|
|
}
|
|
|
|
// IsPublic returns true, if this client is marked as public.
|
|
func (c *ExternalService) IsPublic() bool {
|
|
return false
|
|
}
|
|
|
|
// GetAudience returns the allowed audience(s) for this client.
|
|
func (c *ExternalService) GetAudience() fosite.Arguments {
|
|
return strings.Split(c.Audiences, ",")
|
|
}
|