Using ExternalService and ExternalServiceDTO
This commit is contained in:
@@ -18,7 +18,7 @@ type KeyResult struct {
|
||||
Generated bool `json:"generated,omitempty"`
|
||||
}
|
||||
|
||||
type ClientDTO struct {
|
||||
type ExternalServiceDTO struct {
|
||||
Name string `json:"name"`
|
||||
ID string `json:"clientId"`
|
||||
Secret string `json:"clientSecret"`
|
||||
@@ -28,7 +28,7 @@ type ClientDTO struct {
|
||||
KeyResult *KeyResult `json:"key,omitempty"`
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
type ExternalService struct {
|
||||
ID int64 `xorm:"id pk autoincr"`
|
||||
Name string `xorm:"name"`
|
||||
ClientID string `xorm:"client_id"`
|
||||
@@ -49,8 +49,8 @@ type Client struct {
|
||||
ImpersonateScopes []string
|
||||
}
|
||||
|
||||
func (c *Client) ToDTO() *ClientDTO {
|
||||
c2 := ClientDTO{
|
||||
func (c *ExternalService) ToDTO() *ExternalServiceDTO {
|
||||
c2 := ExternalServiceDTO{
|
||||
Name: c.Name,
|
||||
ID: c.ClientID,
|
||||
Secret: c.Secret,
|
||||
@@ -64,38 +64,38 @@ func (c *Client) ToDTO() *ClientDTO {
|
||||
return &c2
|
||||
}
|
||||
|
||||
func (c *Client) LogID() string {
|
||||
func (c *ExternalService) LogID() string {
|
||||
return "{name: " + c.Name + ", clientID: " + c.ClientID + "}"
|
||||
}
|
||||
|
||||
// GetID returns the client ID.
|
||||
func (c *Client) GetID() string { return c.ClientID }
|
||||
func (c *ExternalService) GetID() string { return c.ClientID }
|
||||
|
||||
// GetHashedSecret returns the hashed secret as it is stored in the store.
|
||||
func (c *Client) GetHashedSecret() []byte {
|
||||
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 *Client) GetRedirectURIs() []string {
|
||||
func (c *ExternalService) GetRedirectURIs() []string {
|
||||
return []string{c.RedirectURI}
|
||||
}
|
||||
|
||||
// GetGrantTypes returns the client's allowed grant types.
|
||||
func (c *Client) GetGrantTypes() fosite.Arguments {
|
||||
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 *Client) GetResponseTypes() fosite.Arguments {
|
||||
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 *Client) GetScopes() fosite.Arguments {
|
||||
func (c *ExternalService) GetScopes() fosite.Arguments {
|
||||
if c.Scopes != nil {
|
||||
return c.Scopes
|
||||
}
|
||||
@@ -114,7 +114,7 @@ func (c *Client) GetScopes() fosite.Arguments {
|
||||
}
|
||||
|
||||
// GetScopes returns the scopes this client is allowed to request on a specific user.
|
||||
func (c *Client) GetScopesOnUser(ctx context.Context, accessControl ac.AccessControl, userID int64) []string {
|
||||
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 {
|
||||
@@ -151,11 +151,11 @@ func (c *Client) GetScopesOnUser(ctx context.Context, accessControl ac.AccessCon
|
||||
}
|
||||
|
||||
// IsPublic returns true, if this client is marked as public.
|
||||
func (c *Client) IsPublic() bool {
|
||||
func (c *ExternalService) IsPublic() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// GetAudience returns the allowed audience(s) for this client.
|
||||
func (c *Client) GetAudience() fosite.Arguments {
|
||||
func (c *ExternalService) GetAudience() fosite.Arguments {
|
||||
return strings.Split(c.Audiences, ",")
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func setupTestEnv(t *testing.T) *Client {
|
||||
func setupTestEnv(t *testing.T) *ExternalService {
|
||||
t.Helper()
|
||||
|
||||
client := &Client{
|
||||
client := &ExternalService{
|
||||
Name: "my-ext-service",
|
||||
ClientID: "RANDOMID",
|
||||
Secret: "RANDOMSECRET",
|
||||
@@ -37,19 +37,19 @@ func TestClient_GetScopesOnUser(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
impersonatePermissions []ac.Permission
|
||||
initTestEnv func(*Client)
|
||||
initTestEnv func(*ExternalService)
|
||||
expectedScopes []string
|
||||
}{
|
||||
{
|
||||
name: "should return nil when the service account has no impersonate permissions",
|
||||
initTestEnv: func(c *Client) {
|
||||
initTestEnv: func(c *ExternalService) {
|
||||
c.SelfPermissions = []ac.Permission{}
|
||||
},
|
||||
expectedScopes: nil,
|
||||
},
|
||||
{
|
||||
name: "should return the 'profile', 'email' and associated RBAC action",
|
||||
initTestEnv: func(c *Client) {
|
||||
initTestEnv: func(c *ExternalService) {
|
||||
c.SelfPermissions = []ac.Permission{
|
||||
{Action: ac.ActionUsersImpersonate, Scope: ac.ScopeUsersAll},
|
||||
}
|
||||
@@ -66,7 +66,7 @@ func TestClient_GetScopesOnUser(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "should return 'entitlements' and associated RBAC action scopes",
|
||||
initTestEnv: func(c *Client) {
|
||||
initTestEnv: func(c *ExternalService) {
|
||||
c.SelfPermissions = []ac.Permission{
|
||||
{Action: ac.ActionUsersImpersonate, Scope: ac.ScopeUsersAll},
|
||||
}
|
||||
@@ -83,7 +83,7 @@ func TestClient_GetScopesOnUser(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "should return 'groups' and associated RBAC action scopes",
|
||||
initTestEnv: func(c *Client) {
|
||||
initTestEnv: func(c *ExternalService) {
|
||||
c.SelfPermissions = []ac.Permission{
|
||||
{Action: ac.ActionUsersImpersonate, Scope: ac.ScopeUsersAll},
|
||||
}
|
||||
@@ -100,7 +100,7 @@ func TestClient_GetScopesOnUser(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "should return all scopes",
|
||||
initTestEnv: func(c *Client) {
|
||||
initTestEnv: func(c *ExternalService) {
|
||||
c.SelfPermissions = []ac.Permission{
|
||||
{Action: ac.ActionUsersImpersonate, Scope: ac.ScopeUsersAll},
|
||||
}
|
||||
@@ -123,7 +123,7 @@ func TestClient_GetScopesOnUser(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "should return stored scopes when the client's impersonate scopes has already been set",
|
||||
initTestEnv: func(c *Client) {
|
||||
initTestEnv: func(c *ExternalService) {
|
||||
c.SignedInUser.Permissions = map[int64]map[string][]string{
|
||||
1: {
|
||||
ac.ActionUsersImpersonate: {ac.ScopeUsersAll},
|
||||
@@ -150,19 +150,19 @@ func TestClient_GetScopes(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
impersonatePermissions []ac.Permission
|
||||
initTestEnv func(*Client)
|
||||
initTestEnv func(*ExternalService)
|
||||
expectedScopes []string
|
||||
}{
|
||||
{
|
||||
name: "should return default scopes when the signed in user is nil",
|
||||
initTestEnv: func(c *Client) {
|
||||
initTestEnv: func(c *ExternalService) {
|
||||
c.SignedInUser = nil
|
||||
},
|
||||
expectedScopes: []string{"profile", "email", "entitlements", "groups"},
|
||||
},
|
||||
{
|
||||
name: "should return additional scopes from signed in user's permissions",
|
||||
initTestEnv: func(c *Client) {
|
||||
initTestEnv: func(c *ExternalService) {
|
||||
c.SignedInUser.Permissions = map[int64]map[string][]string{
|
||||
1: {
|
||||
dashboards.ActionDashboardsRead: {dashboards.ScopeDashboardsAll},
|
||||
@@ -173,14 +173,14 @@ func TestClient_GetScopes(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "should return default scopes when the signed in user has no permissions",
|
||||
initTestEnv: func(c *Client) {
|
||||
initTestEnv: func(c *ExternalService) {
|
||||
c.SignedInUser.Permissions = map[int64]map[string][]string{}
|
||||
},
|
||||
expectedScopes: []string{"profile", "email", "entitlements", "groups"},
|
||||
},
|
||||
{
|
||||
name: "should return stored scopes when the client's scopes has already been set",
|
||||
initTestEnv: func(c *Client) {
|
||||
initTestEnv: func(c *ExternalService) {
|
||||
c.Scopes = []string{"profile", "email", "entitlements", "groups"}
|
||||
},
|
||||
expectedScopes: []string{"profile", "email", "entitlements", "groups"},
|
||||
@@ -199,7 +199,7 @@ func TestClient_GetScopes(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestClient_ToDTO(t *testing.T) {
|
||||
client := &Client{
|
||||
client := &ExternalService{
|
||||
ID: 1,
|
||||
Name: "my-ext-service",
|
||||
ClientID: "test",
|
||||
|
||||
@@ -29,10 +29,10 @@ const (
|
||||
type OAuth2Server interface {
|
||||
// SaveExternalService creates or updates an external service in the database, it generates client_id and secrets and
|
||||
// it ensures that the associated service account has the correct permissions.
|
||||
SaveExternalService(ctx context.Context, cmd *ExternalServiceRegistration) (*ClientDTO, error)
|
||||
SaveExternalService(ctx context.Context, cmd *ExternalServiceRegistration) (*ExternalServiceDTO, error)
|
||||
// GetExternalService retrieves an external service from store by client_id. It populates the SelfPermissions and
|
||||
// SignedInUser from the associated service account.
|
||||
GetExternalService(ctx context.Context, id string) (*Client, error)
|
||||
GetExternalService(ctx context.Context, id string) (*ExternalService, error)
|
||||
|
||||
// HandleTokenRequest handles the client's OAuth2 query to obtain an access_token by presenting its authorization
|
||||
// grant (ex: client_credentials, jwtbearer).
|
||||
@@ -45,10 +45,10 @@ type OAuth2Server interface {
|
||||
//go:generate mockery --name Store --structname MockStore --outpkg oauthtest --filename store_mock.go --output ./oauthtest/
|
||||
|
||||
type Store interface {
|
||||
RegisterExternalService(ctx context.Context, client *Client) error
|
||||
SaveExternalService(ctx context.Context, client *Client) error
|
||||
GetExternalService(ctx context.Context, id string) (*Client, error)
|
||||
GetExternalServiceByName(ctx context.Context, name string) (*Client, error)
|
||||
RegisterExternalService(ctx context.Context, client *ExternalService) error
|
||||
SaveExternalService(ctx context.Context, client *ExternalService) error
|
||||
GetExternalService(ctx context.Context, id string) (*ExternalService, error)
|
||||
GetExternalServiceByName(ctx context.Context, name string) (*ExternalService, error)
|
||||
|
||||
GetExternalServicePublicKey(ctx context.Context, clientID string) (*jose.JSONWebKey, error)
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
var cachedUser = func() *oauthserver.Client {
|
||||
return &oauthserver.Client{
|
||||
var cachedUser = func() *oauthserver.ExternalService {
|
||||
return &oauthserver.ExternalService{
|
||||
Name: "my-ext-service",
|
||||
ClientID: "RANDOMID",
|
||||
Secret: "RANDOMSECRET",
|
||||
|
||||
@@ -132,10 +132,10 @@ func newProvider(config *fosite.Config, storage interface{}, key interface{}) fo
|
||||
// GetExternalService retrieves an external service from store by client_id. It populates the SelfPermissions and
|
||||
// SignedInUser from the associated service account.
|
||||
// For performance reason, the service uses caching.
|
||||
func (s *OAuth2ServiceImpl) GetExternalService(ctx context.Context, id string) (*oauthserver.Client, error) {
|
||||
func (s *OAuth2ServiceImpl) GetExternalService(ctx context.Context, id string) (*oauthserver.ExternalService, error) {
|
||||
entry, ok := s.cache.Get(id)
|
||||
if ok {
|
||||
client, ok := entry.(oauthserver.Client)
|
||||
client, ok := entry.(oauthserver.ExternalService)
|
||||
if ok {
|
||||
s.logger.Debug("GetExternalService: cache hit", "client id", id)
|
||||
return &client, nil
|
||||
@@ -178,7 +178,7 @@ func (s *OAuth2ServiceImpl) GetExternalService(ctx context.Context, id string) (
|
||||
// SaveExternalService creates or updates an external service in the database, it generates client_id and secrets and
|
||||
// it ensures that the associated service account has the correct permissions.
|
||||
// Database consistency is not guaranteed, consider changing this in the future.
|
||||
func (s *OAuth2ServiceImpl) SaveExternalService(ctx context.Context, registration *oauthserver.ExternalServiceRegistration) (*oauthserver.ClientDTO, error) {
|
||||
func (s *OAuth2ServiceImpl) SaveExternalService(ctx context.Context, registration *oauthserver.ExternalServiceRegistration) (*oauthserver.ExternalServiceDTO, error) {
|
||||
if registration == nil {
|
||||
s.logger.Warn("RegisterExternalService called without registration")
|
||||
return nil, nil
|
||||
@@ -199,7 +199,7 @@ func (s *OAuth2ServiceImpl) SaveExternalService(ctx context.Context, registratio
|
||||
// Otherwise, create a new client
|
||||
if client == nil {
|
||||
s.logger.Debug("External service does not yet exist", "external service name", registration.Name)
|
||||
client = &oauthserver.Client{
|
||||
client = &oauthserver.ExternalService{
|
||||
Name: registration.Name,
|
||||
ServiceAccountID: oauthserver.NoServiceAccountID,
|
||||
Audiences: s.cfg.AppURL,
|
||||
|
||||
@@ -103,8 +103,8 @@ func TestOAuth2ServiceImpl_SaveExternalService(t *testing.T) {
|
||||
sa1Profile := sa.ServiceAccountProfileDTO{Id: 1, Name: serviceName, Login: serviceName, OrgId: oauthserver.TmpOrgID, IsDisabled: false, Role: "Viewer"}
|
||||
prevSaID := int64(3)
|
||||
// Using a function to prevent modifying the same object in the tests
|
||||
client1 := func() *oauthserver.Client {
|
||||
return &oauthserver.Client{
|
||||
client1 := func() *oauthserver.ExternalService {
|
||||
return &oauthserver.ExternalService{
|
||||
Name: serviceName,
|
||||
ClientID: "RANDOMID",
|
||||
Secret: "RANDOMSECRET",
|
||||
@@ -136,7 +136,7 @@ func TestOAuth2ServiceImpl_SaveExternalService(t *testing.T) {
|
||||
env.OAuthStore.AssertCalled(t, "GetExternalServiceByName", mock.Anything, mock.MatchedBy(func(name string) bool {
|
||||
return name == serviceName
|
||||
}))
|
||||
env.OAuthStore.AssertCalled(t, "SaveExternalService", mock.Anything, mock.MatchedBy(func(client *oauthserver.Client) bool {
|
||||
env.OAuthStore.AssertCalled(t, "SaveExternalService", mock.Anything, mock.MatchedBy(func(client *oauthserver.ExternalService) bool {
|
||||
ok := client.Name == serviceName
|
||||
ok = ok && client.ClientID != ""
|
||||
ok = ok && client.Secret != ""
|
||||
@@ -163,7 +163,7 @@ func TestOAuth2ServiceImpl_SaveExternalService(t *testing.T) {
|
||||
},
|
||||
mockChecks: func(t *testing.T, env *TestEnv) {
|
||||
// Check that the client has a service account and the correct grant type
|
||||
env.OAuthStore.AssertCalled(t, "SaveExternalService", mock.Anything, mock.MatchedBy(func(client *oauthserver.Client) bool {
|
||||
env.OAuthStore.AssertCalled(t, "SaveExternalService", mock.Anything, mock.MatchedBy(func(client *oauthserver.ExternalService) bool {
|
||||
return client.Name == serviceName &&
|
||||
client.GrantTypes == "client_credentials" && client.ServiceAccountID == sa1.Id
|
||||
}))
|
||||
@@ -192,7 +192,7 @@ func TestOAuth2ServiceImpl_SaveExternalService(t *testing.T) {
|
||||
},
|
||||
mockChecks: func(t *testing.T, env *TestEnv) {
|
||||
// Check that the service has no service account anymore
|
||||
env.OAuthStore.AssertCalled(t, "SaveExternalService", mock.Anything, mock.MatchedBy(func(client *oauthserver.Client) bool {
|
||||
env.OAuthStore.AssertCalled(t, "SaveExternalService", mock.Anything, mock.MatchedBy(func(client *oauthserver.ExternalService) bool {
|
||||
return client.Name == serviceName && client.ServiceAccountID == oauthserver.NoServiceAccountID
|
||||
}))
|
||||
// Check that the service account is retrieved with the correct ID
|
||||
@@ -301,8 +301,8 @@ func TestOAuth2ServiceImpl_SaveExternalService(t *testing.T) {
|
||||
func TestOAuth2ServiceImpl_GetExternalService(t *testing.T) {
|
||||
const serviceName = "my-ext-service"
|
||||
|
||||
dummyClient := func() *oauthserver.Client {
|
||||
return &oauthserver.Client{
|
||||
dummyClient := func() *oauthserver.ExternalService {
|
||||
return &oauthserver.ExternalService{
|
||||
Name: serviceName,
|
||||
ClientID: "RANDOMID",
|
||||
Secret: "RANDOMSECRET",
|
||||
@@ -311,7 +311,7 @@ func TestOAuth2ServiceImpl_GetExternalService(t *testing.T) {
|
||||
ServiceAccountID: 1,
|
||||
}
|
||||
}
|
||||
cachedUser := &oauthserver.Client{
|
||||
cachedUser := &oauthserver.ExternalService{
|
||||
Name: serviceName,
|
||||
ClientID: "RANDOMID",
|
||||
Secret: "RANDOMSECRET",
|
||||
|
||||
@@ -98,7 +98,7 @@ func splitOAuthScopes(requestedScopes fosite.Arguments) (map[string]bool, map[st
|
||||
// handleJWTBearer populates the "impersonation" access_token generated by fosite to match the rfc9068 specifications (entitlements, groups)
|
||||
// It ensures that the user can be impersonated, that the generated token audiences only contain Grafana's AppURL (and token endpoint)
|
||||
// and that entitlements solely contain the user's permissions that the client is allowed to have.
|
||||
func (s *OAuth2ServiceImpl) handleJWTBearer(ctx context.Context, accessRequest fosite.AccessRequester, currentOAuthSessionData *PluginAuthSession, client *oauthserver.Client) error {
|
||||
func (s *OAuth2ServiceImpl) handleJWTBearer(ctx context.Context, accessRequest fosite.AccessRequester, currentOAuthSessionData *PluginAuthSession, client *oauthserver.ExternalService) error {
|
||||
if !accessRequest.GetGrantTypes().ExactOne(string(fosite.GrantTypeJWTBearer)) {
|
||||
return nil
|
||||
}
|
||||
@@ -290,7 +290,7 @@ func (*OAuth2ServiceImpl) filteredImpersonatePermissions(impersonatePermissions
|
||||
}
|
||||
|
||||
// handleClientCredentials populates the client's access_token generated by fosite to match the rfc9068 specifications (entitlements, groups)
|
||||
func (s *OAuth2ServiceImpl) handleClientCredentials(ctx context.Context, accessRequest fosite.AccessRequester, currentOAuthSessionData *PluginAuthSession, client *oauthserver.Client) error {
|
||||
func (s *OAuth2ServiceImpl) handleClientCredentials(ctx context.Context, accessRequest fosite.AccessRequester, currentOAuthSessionData *PluginAuthSession, client *oauthserver.ExternalService) error {
|
||||
if !accessRequest.GetGrantTypes().ExactOne("client_credentials") {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
)
|
||||
|
||||
func TestOAuth2ServiceImpl_handleClientCredentials(t *testing.T) {
|
||||
client1 := &oauthserver.Client{
|
||||
client1 := &oauthserver.ExternalService{
|
||||
Name: "testapp",
|
||||
ClientID: "RANDOMID",
|
||||
GrantTypes: string(fosite.GrantTypeClientCredentials),
|
||||
@@ -53,13 +53,13 @@ func TestOAuth2ServiceImpl_handleClientCredentials(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
scopes []string
|
||||
client *oauthserver.Client
|
||||
client *oauthserver.ExternalService
|
||||
expectedClaims map[string]interface{}
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "no claim without client_credentials grant type",
|
||||
client: &oauthserver.Client{
|
||||
client: &oauthserver.ExternalService{
|
||||
Name: "testapp",
|
||||
ClientID: "RANDOMID",
|
||||
GrantTypes: string(fosite.GrantTypeJWTBearer),
|
||||
@@ -135,7 +135,7 @@ func TestOAuth2ServiceImpl_handleClientCredentials(t *testing.T) {
|
||||
|
||||
func TestOAuth2ServiceImpl_handleJWTBearer(t *testing.T) {
|
||||
now := time.Now()
|
||||
client1 := &oauthserver.Client{
|
||||
client1 := &oauthserver.ExternalService{
|
||||
Name: "testapp",
|
||||
ClientID: "RANDOMID",
|
||||
GrantTypes: string(fosite.GrantTypeJWTBearer),
|
||||
@@ -164,7 +164,7 @@ func TestOAuth2ServiceImpl_handleJWTBearer(t *testing.T) {
|
||||
{ID: 1, Name: "Team 1", OrgID: 1},
|
||||
{ID: 2, Name: "Team 2", OrgID: 1},
|
||||
}
|
||||
client1WithPerm := func(perms []ac.Permission) *oauthserver.Client {
|
||||
client1WithPerm := func(perms []ac.Permission) *oauthserver.ExternalService {
|
||||
client := *client1
|
||||
client.ImpersonatePermissions = perms
|
||||
return &client
|
||||
@@ -174,14 +174,14 @@ func TestOAuth2ServiceImpl_handleJWTBearer(t *testing.T) {
|
||||
name string
|
||||
initEnv func(*TestEnv)
|
||||
scopes []string
|
||||
client *oauthserver.Client
|
||||
client *oauthserver.ExternalService
|
||||
subject string
|
||||
expectedClaims map[string]interface{}
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "no claim without jwtbearer grant type",
|
||||
client: &oauthserver.Client{
|
||||
client: &oauthserver.ExternalService{
|
||||
Name: "testapp",
|
||||
ClientID: "RANDOMID",
|
||||
GrantTypes: string(fosite.GrantTypeClientCredentials),
|
||||
@@ -196,7 +196,7 @@ func TestOAuth2ServiceImpl_handleJWTBearer(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "err client is not allowed to impersonate",
|
||||
client: &oauthserver.Client{
|
||||
client: &oauthserver.ExternalService{
|
||||
Name: "testapp",
|
||||
ClientID: "RANDOMID",
|
||||
GrantTypes: string(fosite.GrantTypeJWTBearer),
|
||||
@@ -477,7 +477,7 @@ func TestOAuth2ServiceImpl_HandleTokenRequest(t *testing.T) {
|
||||
client1Secret := "RANDOMSECRET"
|
||||
hashedSecret, err := bcrypt.GenerateFromPassword([]byte(client1Secret), bcrypt.DefaultCost)
|
||||
require.NoError(t, err)
|
||||
client1 := &oauthserver.Client{
|
||||
client1 := &oauthserver.ExternalService{
|
||||
Name: "testapp",
|
||||
ClientID: "RANDOMID",
|
||||
Secret: string(hashedSecret),
|
||||
|
||||
@@ -9,18 +9,18 @@ import (
|
||||
)
|
||||
|
||||
type FakeService struct {
|
||||
ExpectedClient *oauthserver.Client
|
||||
ExpectedClient *oauthserver.ExternalService
|
||||
ExpectedKey *jose.JSONWebKey
|
||||
ExpectedErr error
|
||||
}
|
||||
|
||||
var _ oauthserver.OAuth2Server = &FakeService{}
|
||||
|
||||
func (s *FakeService) SaveExternalService(ctx context.Context, cmd *oauthserver.ExternalServiceRegistration) (*oauthserver.ClientDTO, error) {
|
||||
func (s *FakeService) SaveExternalService(ctx context.Context, cmd *oauthserver.ExternalServiceRegistration) (*oauthserver.ExternalServiceDTO, error) {
|
||||
return s.ExpectedClient.ToDTO(), s.ExpectedErr
|
||||
}
|
||||
|
||||
func (s *FakeService) GetExternalService(ctx context.Context, id string) (*oauthserver.Client, error) {
|
||||
func (s *FakeService) GetExternalService(ctx context.Context, id string) (*oauthserver.ExternalService, error) {
|
||||
return s.ExpectedClient, s.ExpectedErr
|
||||
}
|
||||
|
||||
|
||||
@@ -17,19 +17,19 @@ type MockStore struct {
|
||||
}
|
||||
|
||||
// GetExternalService provides a mock function with given fields: ctx, id
|
||||
func (_m *MockStore) GetExternalService(ctx context.Context, id string) (*oauthserver.Client, error) {
|
||||
func (_m *MockStore) GetExternalService(ctx context.Context, id string) (*oauthserver.ExternalService, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
||||
var r0 *oauthserver.Client
|
||||
var r0 *oauthserver.ExternalService
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*oauthserver.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*oauthserver.ExternalService, error)); ok {
|
||||
return rf(ctx, id)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *oauthserver.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *oauthserver.ExternalService); ok {
|
||||
r0 = rf(ctx, id)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*oauthserver.Client)
|
||||
r0 = ret.Get(0).(*oauthserver.ExternalService)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,19 +43,19 @@ func (_m *MockStore) GetExternalService(ctx context.Context, id string) (*oauths
|
||||
}
|
||||
|
||||
// GetExternalServiceByName provides a mock function with given fields: ctx, name
|
||||
func (_m *MockStore) GetExternalServiceByName(ctx context.Context, name string) (*oauthserver.Client, error) {
|
||||
func (_m *MockStore) GetExternalServiceByName(ctx context.Context, name string) (*oauthserver.ExternalService, error) {
|
||||
ret := _m.Called(ctx, name)
|
||||
|
||||
var r0 *oauthserver.Client
|
||||
var r0 *oauthserver.ExternalService
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*oauthserver.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (*oauthserver.ExternalService, error)); ok {
|
||||
return rf(ctx, name)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *oauthserver.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) *oauthserver.ExternalService); ok {
|
||||
r0 = rf(ctx, name)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*oauthserver.Client)
|
||||
r0 = ret.Get(0).(*oauthserver.ExternalService)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,11 +95,11 @@ func (_m *MockStore) GetExternalServicePublicKey(ctx context.Context, clientID s
|
||||
}
|
||||
|
||||
// RegisterExternalService provides a mock function with given fields: ctx, client
|
||||
func (_m *MockStore) RegisterExternalService(ctx context.Context, client *oauthserver.Client) error {
|
||||
func (_m *MockStore) RegisterExternalService(ctx context.Context, client *oauthserver.ExternalService) error {
|
||||
ret := _m.Called(ctx, client)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *oauthserver.Client) error); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *oauthserver.ExternalService) error); ok {
|
||||
r0 = rf(ctx, client)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
@@ -109,11 +109,11 @@ func (_m *MockStore) RegisterExternalService(ctx context.Context, client *oauths
|
||||
}
|
||||
|
||||
// SaveExternalService provides a mock function with given fields: ctx, client
|
||||
func (_m *MockStore) SaveExternalService(ctx context.Context, client *oauthserver.Client) error {
|
||||
func (_m *MockStore) SaveExternalService(ctx context.Context, client *oauthserver.ExternalService) error {
|
||||
ret := _m.Called(ctx, client)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *oauthserver.Client) error); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *oauthserver.ExternalService) error); ok {
|
||||
r0 = rf(ctx, client)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
|
||||
@@ -22,7 +22,7 @@ func NewStore(db db.DB) oauthserver.Store {
|
||||
return &store{db: db}
|
||||
}
|
||||
|
||||
func createImpersonatePermissions(sess *db.Session, client *oauthserver.Client) error {
|
||||
func createImpersonatePermissions(sess *db.Session, client *oauthserver.ExternalService) error {
|
||||
if len(client.ImpersonatePermissions) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -38,7 +38,7 @@ func createImpersonatePermissions(sess *db.Session, client *oauthserver.Client)
|
||||
return err
|
||||
}
|
||||
|
||||
func registerExternalService(sess *db.Session, client *oauthserver.Client) error {
|
||||
func registerExternalService(sess *db.Session, client *oauthserver.ExternalService) error {
|
||||
insertQuery := []interface{}{
|
||||
`INSERT INTO oauth_client (name, client_id, secret, grant_types, audiences, service_account_id, public_pem, redirect_uri) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
client.Name,
|
||||
@@ -57,13 +57,13 @@ func registerExternalService(sess *db.Session, client *oauthserver.Client) error
|
||||
return createImpersonatePermissions(sess, client)
|
||||
}
|
||||
|
||||
func (s *store) RegisterExternalService(ctx context.Context, client *oauthserver.Client) error {
|
||||
func (s *store) RegisterExternalService(ctx context.Context, client *oauthserver.ExternalService) error {
|
||||
return s.db.WithTransactionalDbSession(ctx, func(sess *db.Session) error {
|
||||
return registerExternalService(sess, client)
|
||||
})
|
||||
}
|
||||
|
||||
func recreateImpersonatePermissions(sess *db.Session, client *oauthserver.Client, prevClientID string) error {
|
||||
func recreateImpersonatePermissions(sess *db.Session, client *oauthserver.ExternalService, prevClientID string) error {
|
||||
deletePermQuery := `DELETE FROM oauth_impersonate_permission WHERE client_id = ?`
|
||||
if _, errDelPerm := sess.Exec(deletePermQuery, prevClientID); errDelPerm != nil {
|
||||
return errDelPerm
|
||||
@@ -76,7 +76,7 @@ func recreateImpersonatePermissions(sess *db.Session, client *oauthserver.Client
|
||||
return createImpersonatePermissions(sess, client)
|
||||
}
|
||||
|
||||
func updateExternalService(sess *db.Session, client *oauthserver.Client, prevClientID string) error {
|
||||
func updateExternalService(sess *db.Session, client *oauthserver.ExternalService, prevClientID string) error {
|
||||
updateQuery := []interface{}{
|
||||
`UPDATE oauth_client SET client_id = ?, secret = ?, grant_types = ?, audiences = ?, service_account_id = ?, public_pem = ?, redirect_uri = ? WHERE name = ?`,
|
||||
client.ClientID,
|
||||
@@ -95,7 +95,7 @@ func updateExternalService(sess *db.Session, client *oauthserver.Client, prevCli
|
||||
return recreateImpersonatePermissions(sess, client, prevClientID)
|
||||
}
|
||||
|
||||
func (s *store) SaveExternalService(ctx context.Context, client *oauthserver.Client) error {
|
||||
func (s *store) SaveExternalService(ctx context.Context, client *oauthserver.ExternalService) error {
|
||||
if client.Name == "" {
|
||||
return oauthserver.ErrClientRequiredName
|
||||
}
|
||||
@@ -116,8 +116,8 @@ func (s *store) SaveExternalService(ctx context.Context, client *oauthserver.Cli
|
||||
})
|
||||
}
|
||||
|
||||
func (s *store) GetExternalService(ctx context.Context, id string) (*oauthserver.Client, error) {
|
||||
res := &oauthserver.Client{}
|
||||
func (s *store) GetExternalService(ctx context.Context, id string) (*oauthserver.ExternalService, error) {
|
||||
res := &oauthserver.ExternalService{}
|
||||
if id == "" {
|
||||
return nil, oauthserver.ErrClientRequiredID
|
||||
}
|
||||
@@ -145,7 +145,7 @@ func (s *store) GetExternalService(ctx context.Context, id string) (*oauthserver
|
||||
// GetPublicKey returns public key, issued by 'issuer', and assigned for subject. Public key is used to check
|
||||
// signature of jwt assertion in authorization grants.
|
||||
func (s *store) GetExternalServicePublicKey(ctx context.Context, clientID string) (*jose.JSONWebKey, error) {
|
||||
res := &oauthserver.Client{}
|
||||
res := &oauthserver.ExternalService{}
|
||||
if clientID == "" {
|
||||
return nil, oauthserver.ErrClientRequiredID
|
||||
}
|
||||
@@ -183,8 +183,8 @@ func (s *store) GetExternalServicePublicKey(ctx context.Context, clientID string
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *store) GetExternalServiceByName(ctx context.Context, name string) (*oauthserver.Client, error) {
|
||||
res := &oauthserver.Client{}
|
||||
func (s *store) GetExternalServiceByName(ctx context.Context, name string) (*oauthserver.ExternalService, error) {
|
||||
res := &oauthserver.ExternalService{}
|
||||
if name == "" {
|
||||
return nil, oauthserver.ErrClientRequiredName
|
||||
}
|
||||
@@ -198,8 +198,8 @@ func (s *store) GetExternalServiceByName(ctx context.Context, name string) (*oau
|
||||
return res, err
|
||||
}
|
||||
|
||||
func getExternalServiceByName(sess *db.Session, name string) (*oauthserver.Client, error) {
|
||||
res := &oauthserver.Client{}
|
||||
func getExternalServiceByName(sess *db.Session, name string) (*oauthserver.ExternalService, error) {
|
||||
res := &oauthserver.ExternalService{}
|
||||
getClientQuery := `SELECT
|
||||
id, name, client_id, secret, grant_types, audiences, service_account_id, public_pem, redirect_uri
|
||||
FROM oauth_client
|
||||
|
||||
@@ -17,12 +17,12 @@ func TestStore_RegisterAndGetClient(t *testing.T) {
|
||||
s := &store{db: db.InitTestDB(t, db.InitTestDBOpt{FeatureFlags: []string{featuremgmt.FlagExternalServiceAuth}})}
|
||||
tests := []struct {
|
||||
name string
|
||||
client oauthserver.Client
|
||||
client oauthserver.ExternalService
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "register and get",
|
||||
client: oauthserver.Client{
|
||||
client: oauthserver.ExternalService{
|
||||
Name: "The Worst App Ever",
|
||||
ClientID: "ANonRandomClientID",
|
||||
Secret: "ICouldKeepSecrets",
|
||||
@@ -59,7 +59,7 @@ dCBBIFJlZ3VsYXIgQmFzZTY0IEVuY29kZWQgU3RyaW5nLi4uCg==
|
||||
},
|
||||
{
|
||||
name: "register with impersonate permissions and get",
|
||||
client: oauthserver.Client{
|
||||
client: oauthserver.ExternalService{
|
||||
Name: "The Best App Ever",
|
||||
ClientID: "AnAlmostRandomClientID",
|
||||
Secret: "ICannotKeepSecrets",
|
||||
@@ -80,7 +80,7 @@ dCBBIFJlZ3VsYXIgQmFzZTY0IEVuY29kZWQgU3RyaW5nLi4uCg==
|
||||
},
|
||||
{
|
||||
name: "register with audiences and get",
|
||||
client: oauthserver.Client{
|
||||
client: oauthserver.ExternalService{
|
||||
Name: "The Most Normal App Ever",
|
||||
ClientID: "AnAlmostRandomClientIDAgain",
|
||||
Secret: "ICanKeepSecretsEventually",
|
||||
@@ -111,7 +111,7 @@ dCBBIFJlZ3VsYXIgQmFzZTY0IEVuY29kZWQgU3RyaW5nLi4uCg==
|
||||
}
|
||||
|
||||
func TestStore_SaveExternalService(t *testing.T) {
|
||||
client1 := oauthserver.Client{
|
||||
client1 := oauthserver.ExternalService{
|
||||
Name: "my-external-service",
|
||||
ClientID: "ClientID",
|
||||
Secret: "Secret",
|
||||
@@ -136,42 +136,42 @@ func TestStore_SaveExternalService(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
runs []oauthserver.Client
|
||||
runs []oauthserver.ExternalService
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "error no name",
|
||||
runs: []oauthserver.Client{{}},
|
||||
runs: []oauthserver.ExternalService{{}},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "simple register",
|
||||
runs: []oauthserver.Client{client1},
|
||||
runs: []oauthserver.ExternalService{client1},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "no update",
|
||||
runs: []oauthserver.Client{client1, client1},
|
||||
runs: []oauthserver.ExternalService{client1, client1},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "add permissions",
|
||||
runs: []oauthserver.Client{client1, client1WithPerm},
|
||||
runs: []oauthserver.ExternalService{client1, client1WithPerm},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "remove permissions",
|
||||
runs: []oauthserver.Client{client1WithPerm, client1},
|
||||
runs: []oauthserver.ExternalService{client1WithPerm, client1},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "update id and secrets",
|
||||
runs: []oauthserver.Client{client1, client1WithNewSecrets},
|
||||
runs: []oauthserver.ExternalService{client1, client1WithNewSecrets},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "update audience",
|
||||
runs: []oauthserver.Client{client1, client1WithAud},
|
||||
runs: []oauthserver.ExternalService{client1, client1WithAud},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
@@ -193,7 +193,7 @@ func TestStore_SaveExternalService(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestStore_GetExternalServiceByName(t *testing.T) {
|
||||
client1 := oauthserver.Client{
|
||||
client1 := oauthserver.ExternalService{
|
||||
Name: "my-external-service",
|
||||
ClientID: "ClientID",
|
||||
Secret: "Secret",
|
||||
@@ -203,7 +203,7 @@ func TestStore_GetExternalServiceByName(t *testing.T) {
|
||||
ImpersonatePermissions: []accesscontrol.Permission{},
|
||||
RedirectURI: "/whereto",
|
||||
}
|
||||
client2 := oauthserver.Client{
|
||||
client2 := oauthserver.ExternalService{
|
||||
Name: "my-external-service-2",
|
||||
ClientID: "ClientID2",
|
||||
Secret: "Secret2",
|
||||
@@ -224,7 +224,7 @@ func TestStore_GetExternalServiceByName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
search string
|
||||
want *oauthserver.Client
|
||||
want *oauthserver.ExternalService
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
@@ -268,8 +268,8 @@ func TestStore_GetExternalServiceByName(t *testing.T) {
|
||||
|
||||
func TestStore_GetExternalServicePublicKey(t *testing.T) {
|
||||
clientID := "ClientID"
|
||||
createClient := func(clientID string, publicPem string) *oauthserver.Client {
|
||||
return &oauthserver.Client{
|
||||
createClient := func(clientID string, publicPem string) *oauthserver.ExternalService {
|
||||
return &oauthserver.ExternalService{
|
||||
Name: "my-external-service",
|
||||
ClientID: clientID,
|
||||
Secret: "Secret",
|
||||
@@ -283,7 +283,7 @@ func TestStore_GetExternalServicePublicKey(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
client *oauthserver.Client
|
||||
client *oauthserver.ExternalService
|
||||
clientID string
|
||||
want *jose.JSONWebKey
|
||||
wantErr bool
|
||||
@@ -336,7 +336,7 @@ mgGaC8vUIigFQVsVB+v/HZ4yG1Rcvysig+tyNk1dZQpozpFc2dGmzHlGhw==
|
||||
}
|
||||
}
|
||||
|
||||
func compareClientToStored(t *testing.T, s *store, wanted *oauthserver.Client) {
|
||||
func compareClientToStored(t *testing.T, s *store, wanted *oauthserver.ExternalService) {
|
||||
ctx := context.Background()
|
||||
stored, err := s.GetExternalService(ctx, wanted.ClientID)
|
||||
require.NoError(t, err)
|
||||
@@ -345,7 +345,7 @@ func compareClientToStored(t *testing.T, s *store, wanted *oauthserver.Client) {
|
||||
compareClients(t, stored, wanted)
|
||||
}
|
||||
|
||||
func compareClients(t *testing.T, stored *oauthserver.Client, wanted *oauthserver.Client) {
|
||||
func compareClients(t *testing.T, stored *oauthserver.ExternalService, wanted *oauthserver.ExternalService) {
|
||||
// Reset ID so we can compare
|
||||
require.NotZero(t, stored.ID)
|
||||
stored.ID = 0
|
||||
|
||||
Reference in New Issue
Block a user