Skip to content

Commit

Permalink
fix: sync resource creation/delation with authz
Browse files Browse the repository at this point in the history
  • Loading branch information
nsklikas committed Jul 16, 2024
1 parent 35e3348 commit 55d02df
Show file tree
Hide file tree
Showing 18 changed files with 255 additions and 110 deletions.
20 changes: 10 additions & 10 deletions internal/authorization/resource_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,42 +38,42 @@ func (a *Authorizer) getResource(resourceID, resourceType string) string {
return resourceType + ":" + resourceID
}

func (a *Authorizer) CreateClient(ctx context.Context, clientID string) error {
func (a *Authorizer) SetCreateClientEntitlements(ctx context.Context, clientID string) error {
return a.createTuple(ctx, a.getResource(clientID, CLIENT_TYPE))
}

func (a *Authorizer) DeleteClient(ctx context.Context, clientID string) error {
func (a *Authorizer) SetDeleteClientEntitlements(ctx context.Context, clientID string) error {
return a.deleteTuple(ctx, a.getResource(clientID, CLIENT_TYPE))
}

func (a *Authorizer) CreateIdentity(ctx context.Context, IdentityID string) error {
func (a *Authorizer) SetCreateIdentityEntitlements(ctx context.Context, IdentityID string) error {
return a.createTuple(ctx, a.getResource(IdentityID, IDENTITY_TYPE))
}

func (a *Authorizer) DeleteIdentity(ctx context.Context, IdentityID string) error {
func (a *Authorizer) SetDeleteIdentityEntitlements(ctx context.Context, IdentityID string) error {
return a.deleteTuple(ctx, a.getResource(IdentityID, IDENTITY_TYPE))
}

func (a *Authorizer) CreateProvider(ctx context.Context, providerID string) error {
func (a *Authorizer) SetCreateProviderEntitlements(ctx context.Context, providerID string) error {
return a.createTuple(ctx, a.getResource(providerID, PROVIDER_TYPE))
}

func (a *Authorizer) DeleteProvider(ctx context.Context, providerID string) error {
func (a *Authorizer) SetDeleteProviderEntitlements(ctx context.Context, providerID string) error {
return a.deleteTuple(ctx, a.getResource(providerID, PROVIDER_TYPE))
}

func (a *Authorizer) CreateRule(ctx context.Context, ruleID string) error {
func (a *Authorizer) SetCreateRuleEntitlements(ctx context.Context, ruleID string) error {
return a.createTuple(ctx, a.getResource(ruleID, RULE_TYPE))
}

func (a *Authorizer) DeleteRule(ctx context.Context, ruleID string) error {
func (a *Authorizer) SetDeleteRuleEntitlements(ctx context.Context, ruleID string) error {
return a.deleteTuple(ctx, a.getResource(ruleID, RULE_TYPE))
}

func (a *Authorizer) CreateSchema(ctx context.Context, schemeID string) error {
func (a *Authorizer) SetCreateSchemaEntitlements(ctx context.Context, schemeID string) error {
return a.createTuple(ctx, a.getResource(schemeID, SCHEME_TYPE))
}

func (a *Authorizer) DeleteSchema(ctx context.Context, schemeID string) error {
func (a *Authorizer) SetDeleteSchemaEntitlements(ctx context.Context, schemeID string) error {
return a.deleteTuple(ctx, a.getResource(schemeID, SCHEME_TYPE))
}
5 changes: 5 additions & 0 deletions pkg/clients/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ type HydraClientInterface interface {

type OAuth2Client = hClient.OAuth2Client

type AuthorizerInterface interface {
SetCreateClientEntitlements(context.Context, string) error
SetDeleteClientEntitlements(context.Context, string) error
}

type ServiceInterface interface {
GetClient(context.Context, string) (*ServiceResponse, error)
CreateClient(context.Context, *hClient.OAuth2Client) (*ServiceResponse, error)
Expand Down
12 changes: 10 additions & 2 deletions pkg/clients/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type ServiceResponse struct {

type Service struct {
hydra HydraClientInterface
authz AuthorizerInterface

tracer trace.Tracer
monitor monitoring.MonitorInterface
Expand All @@ -61,6 +62,7 @@ func (s *Service) GetClient(ctx context.Context, clientID string) (*ServiceRespo
}
ret.ServiceError = se
}

ret.Resp = c
return ret, nil
}
Expand All @@ -81,7 +83,9 @@ func (s *Service) DeleteClient(ctx context.Context, clientID string) (*ServiceRe
return nil, err
}
ret.ServiceError = se
return ret, nil
}
s.authz.SetDeleteClientEntitlements(ctx, clientID)
return ret, nil
}

Expand All @@ -96,14 +100,17 @@ func (s *Service) CreateClient(ctx context.Context, client *hClient.OAuth2Client
OAuth2Client(*client).
Execute()

ret.Resp = c
if err != nil {
se, err := s.parseServiceError(resp)
if err != nil {
return nil, err
}
ret.ServiceError = se
return ret, nil
}
ret.Resp = c
s.authz.SetCreateClientEntitlements(ctx, *c.ClientId)

return ret, nil
}

Expand Down Expand Up @@ -199,10 +206,11 @@ func (s *Service) parseServiceError(r *http.Response) (*ErrorOAuth2, error) {
return se, nil
}

func NewService(hydra HydraClientInterface, tracer trace.Tracer, monitor monitoring.MonitorInterface, logger logging.LoggerInterface) *Service {
func NewService(hydra HydraClientInterface, authz AuthorizerInterface, tracer trace.Tracer, monitor monitoring.MonitorInterface, logger logging.LoggerInterface) *Service {
s := new(Service)

s.hydra = hydra
s.authz = authz

s.monitor = monitor
s.tracer = tracer
Expand Down
42 changes: 29 additions & 13 deletions pkg/clients/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ func TestGetClientSuccess(t *testing.T) {
mockLogger := NewMockLoggerInterface(ctrl)
mockHydra := NewMockHydraClientInterface(ctrl)
mockTracer := NewMockTracer(ctrl)
mockMonitor := monitoring.NewMockMonitorInterface(ctrl)
mockMonitor := NewMockMonitorInterface(ctrl)
mockAuthz := NewMockAuthorizerInterface(ctrl)
mockHydraOAuth2Api := NewMockOAuth2Api(ctrl)

const clientId = "client_id"
Expand All @@ -49,7 +50,7 @@ func TestGetClientSuccess(t *testing.T) {
mockHydraOAuth2Api.EXPECT().GetOAuth2ClientExecute(gomock.Any()).Times(1).Return(c, new(http.Response), nil)
mockTracer.EXPECT().Start(ctx, "hydra.OAuth2Api.GetOAuth2Client").Times(1).Return(nil, trace.SpanFromContext(ctx))

resp, err := NewService(mockHydra, mockTracer, mockMonitor, mockLogger).GetClient(ctx, clientId)
resp, err := NewService(mockHydra, mockAuthz, mockTracer, mockMonitor, mockLogger).GetClient(ctx, clientId)

if resp.ServiceError != nil {
t.Fatal("expected serviceError to be nil, got: ", resp.ServiceError)
Expand All @@ -70,6 +71,7 @@ func TestGetClientFails(t *testing.T) {
mockHydra := NewMockHydraClientInterface(ctrl)
mockTracer := NewMockTracer(ctrl)
mockMonitor := monitoring.NewMockMonitorInterface(ctrl)
mockAuthz := NewMockAuthorizerInterface(ctrl)
mockHydraOAuth2Api := NewMockOAuth2Api(ctrl)

const clientId = "client_id"
Expand All @@ -91,7 +93,7 @@ func TestGetClientFails(t *testing.T) {
mockHydraOAuth2Api.EXPECT().GetOAuth2ClientExecute(gomock.Any()).Times(1).Return(nil, serviceResp, fmt.Errorf("error"))
mockTracer.EXPECT().Start(ctx, "hydra.OAuth2Api.GetOAuth2Client").Times(1).Return(nil, trace.SpanFromContext(ctx))

resp, err := NewService(mockHydra, mockTracer, mockMonitor, mockLogger).GetClient(ctx, clientId)
resp, err := NewService(mockHydra, mockAuthz, mockTracer, mockMonitor, mockLogger).GetClient(ctx, clientId)
expectedError := new(ErrorOAuth2)
expectedError.Error = *errResp.Error
expectedError.ErrorDescription = *errResp.ErrorDescription
Expand All @@ -112,6 +114,7 @@ func TestDeleteClientSuccess(t *testing.T) {
mockHydra := NewMockHydraClientInterface(ctrl)
mockTracer := NewMockTracer(ctrl)
mockMonitor := monitoring.NewMockMonitorInterface(ctrl)
mockAuthz := NewMockAuthorizerInterface(ctrl)
mockHydraOAuth2Api := NewMockOAuth2Api(ctrl)

const clientId = "client_id"
Expand All @@ -123,12 +126,13 @@ func TestDeleteClientSuccess(t *testing.T) {
}

ctx := context.Background()
mockAuthz.EXPECT().SetDeleteClientEntitlements(gomock.Any(), clientId)
mockHydra.EXPECT().OAuth2Api().Times(1).Return(mockHydraOAuth2Api)
mockHydraOAuth2Api.EXPECT().DeleteOAuth2Client(gomock.Any(), clientId).Times(1).Return(clientReq)
mockHydraOAuth2Api.EXPECT().DeleteOAuth2ClientExecute(gomock.Any()).Times(1).Return(new(http.Response), nil)
mockTracer.EXPECT().Start(ctx, "hydra.OAuth2Api.DeleteOAuth2Client").Times(1).Return(nil, trace.SpanFromContext(ctx))

resp, err := NewService(mockHydra, mockTracer, mockMonitor, mockLogger).DeleteClient(ctx, clientId)
resp, err := NewService(mockHydra, mockAuthz, mockTracer, mockMonitor, mockLogger).DeleteClient(ctx, clientId)

if resp.ServiceError != nil {
t.Fatal("expected serviceError to be nil, got: ", resp.ServiceError)
Expand All @@ -149,6 +153,7 @@ func TestDeleteClientFails(t *testing.T) {
mockHydra := NewMockHydraClientInterface(ctrl)
mockTracer := NewMockTracer(ctrl)
mockMonitor := monitoring.NewMockMonitorInterface(ctrl)
mockAuthz := NewMockAuthorizerInterface(ctrl)
mockHydraOAuth2Api := NewMockOAuth2Api(ctrl)

const clientId = "client_id"
Expand All @@ -171,7 +176,7 @@ func TestDeleteClientFails(t *testing.T) {
mockHydraOAuth2Api.EXPECT().DeleteOAuth2ClientExecute(gomock.Any()).Times(1).Return(serviceResp, fmt.Errorf("error"))
mockTracer.EXPECT().Start(ctx, "hydra.OAuth2Api.DeleteOAuth2Client").Times(1).Return(nil, trace.SpanFromContext(ctx))

resp, err := NewService(mockHydra, mockTracer, mockMonitor, mockLogger).DeleteClient(ctx, clientId)
resp, err := NewService(mockHydra, mockAuthz, mockTracer, mockMonitor, mockLogger).DeleteClient(ctx, clientId)
expectedError := new(ErrorOAuth2)
expectedError.Error = *errResp.Error
expectedError.ErrorDescription = *errResp.ErrorDescription
Expand All @@ -193,20 +198,24 @@ func TestCreateClientSuccess(t *testing.T) {
mockHydra := NewMockHydraClientInterface(ctrl)
mockTracer := NewMockTracer(ctrl)
mockMonitor := monitoring.NewMockMonitorInterface(ctrl)
mockAuthz := NewMockAuthorizerInterface(ctrl)
mockHydraOAuth2Api := NewMockOAuth2Api(ctrl)

c := hClient.NewOAuth2Client()
c.SetClientId("client_id")
clientReq := hClient.OAuth2ApiCreateOAuth2ClientRequest{
ApiService: mockHydraOAuth2Api,
}

ctx := context.Background()

mockAuthz.EXPECT().SetCreateClientEntitlements(gomock.Any(), "client_id")
mockHydra.EXPECT().OAuth2Api().Times(1).Return(mockHydraOAuth2Api)
mockHydraOAuth2Api.EXPECT().CreateOAuth2Client(gomock.Any()).Times(1).Return(clientReq)
mockHydraOAuth2Api.EXPECT().CreateOAuth2ClientExecute(gomock.Any()).Times(1).Return(c, new(http.Response), nil)
mockTracer.EXPECT().Start(ctx, "hydra.OAuth2Api.CreateOAuth2Client").Times(1).Return(nil, trace.SpanFromContext(ctx))

resp, err := NewService(mockHydra, mockTracer, mockMonitor, mockLogger).CreateClient(ctx, c)
resp, err := NewService(mockHydra, mockAuthz, mockTracer, mockMonitor, mockLogger).CreateClient(ctx, c)

if resp.ServiceError != nil {
t.Fatal("expected serviceError to be nil, got: ", resp.ServiceError)
Expand All @@ -227,6 +236,7 @@ func TestCreateClientFails(t *testing.T) {
mockHydra := NewMockHydraClientInterface(ctrl)
mockTracer := NewMockTracer(ctrl)
mockMonitor := monitoring.NewMockMonitorInterface(ctrl)
mockAuthz := NewMockAuthorizerInterface(ctrl)
mockHydraOAuth2Api := NewMockOAuth2Api(ctrl)

c := hClient.NewOAuth2Client()
Expand All @@ -248,7 +258,7 @@ func TestCreateClientFails(t *testing.T) {
mockHydraOAuth2Api.EXPECT().CreateOAuth2ClientExecute(gomock.Any()).Times(1).Return(nil, serviceResp, fmt.Errorf("error"))
mockTracer.EXPECT().Start(ctx, "hydra.OAuth2Api.CreateOAuth2Client").Times(1).Return(nil, trace.SpanFromContext(ctx))

resp, err := NewService(mockHydra, mockTracer, mockMonitor, mockLogger).CreateClient(ctx, c)
resp, err := NewService(mockHydra, mockAuthz, mockTracer, mockMonitor, mockLogger).CreateClient(ctx, c)
expectedError := new(ErrorOAuth2)
expectedError.Error = *errResp.Error
expectedError.ErrorDescription = *errResp.ErrorDescription
Expand All @@ -270,6 +280,7 @@ func TestUpdateClientSuccess(t *testing.T) {
mockHydra := NewMockHydraClientInterface(ctrl)
mockTracer := NewMockTracer(ctrl)
mockMonitor := monitoring.NewMockMonitorInterface(ctrl)
mockAuthz := NewMockAuthorizerInterface(ctrl)
mockHydraOAuth2Api := NewMockOAuth2Api(ctrl)

const clientId = "client_id"
Expand All @@ -285,7 +296,7 @@ func TestUpdateClientSuccess(t *testing.T) {
mockHydraOAuth2Api.EXPECT().SetOAuth2ClientExecute(gomock.Any()).Times(1).Return(c, new(http.Response), nil)
mockTracer.EXPECT().Start(ctx, "hydra.OAuth2Api.SetOAuth2Client").Times(1).Return(nil, trace.SpanFromContext(ctx))

resp, err := NewService(mockHydra, mockTracer, mockMonitor, mockLogger).UpdateClient(ctx, c)
resp, err := NewService(mockHydra, mockAuthz, mockTracer, mockMonitor, mockLogger).UpdateClient(ctx, c)

if resp.ServiceError != nil {
t.Fatal("expected serviceError to be nil, got: ", resp.ServiceError)
Expand All @@ -306,6 +317,7 @@ func TestUpdateClientFails(t *testing.T) {
mockHydra := NewMockHydraClientInterface(ctrl)
mockTracer := NewMockTracer(ctrl)
mockMonitor := monitoring.NewMockMonitorInterface(ctrl)
mockAuthz := NewMockAuthorizerInterface(ctrl)
mockHydraOAuth2Api := NewMockOAuth2Api(ctrl)

const clientId = "client_id"
Expand All @@ -329,7 +341,7 @@ func TestUpdateClientFails(t *testing.T) {
mockHydraOAuth2Api.EXPECT().SetOAuth2ClientExecute(gomock.Any()).Times(1).Return(nil, serviceResp, fmt.Errorf("error"))
mockTracer.EXPECT().Start(ctx, "hydra.OAuth2Api.SetOAuth2Client").Times(1).Return(nil, trace.SpanFromContext(ctx))

resp, err := NewService(mockHydra, mockTracer, mockMonitor, mockLogger).UpdateClient(ctx, c)
resp, err := NewService(mockHydra, mockAuthz, mockTracer, mockMonitor, mockLogger).UpdateClient(ctx, c)
expectedError := new(ErrorOAuth2)
expectedError.Error = *errResp.Error
expectedError.ErrorDescription = *errResp.ErrorDescription
Expand All @@ -351,6 +363,7 @@ func TestListClientSuccess(t *testing.T) {
mockHydra := NewMockHydraClientInterface(ctrl)
mockTracer := NewMockTracer(ctrl)
mockMonitor := monitoring.NewMockMonitorInterface(ctrl)
mockAuthz := NewMockAuthorizerInterface(ctrl)
mockHydraOAuth2Api := NewMockOAuth2Api(ctrl)

const clientId = "client_id"
Expand Down Expand Up @@ -385,7 +398,7 @@ func TestListClientSuccess(t *testing.T) {
},
)

resp, err := NewService(mockHydra, mockTracer, mockMonitor, mockLogger).ListClients(ctx, listReq)
resp, err := NewService(mockHydra, mockAuthz, mockTracer, mockMonitor, mockLogger).ListClients(ctx, listReq)

if resp.ServiceError != nil {
t.Fatal("expected serviceError to be nil, got: ", resp.ServiceError)
Expand All @@ -411,6 +424,7 @@ func TestListClientFails(t *testing.T) {
mockHydra := NewMockHydraClientInterface(ctrl)
mockTracer := NewMockTracer(ctrl)
mockMonitor := monitoring.NewMockMonitorInterface(ctrl)
mockAuthz := NewMockAuthorizerInterface(ctrl)
mockHydraOAuth2Api := NewMockOAuth2Api(ctrl)

errResp := hClient.NewErrorOAuth2()
Expand All @@ -432,7 +446,7 @@ func TestListClientFails(t *testing.T) {
mockHydraOAuth2Api.EXPECT().ListOAuth2ClientsExecute(gomock.Any()).Times(1).Return(nil, serviceResp, fmt.Errorf("error"))
mockTracer.EXPECT().Start(ctx, "hydra.OAuth2Api.ListOAuth2Clients").Times(1).Return(nil, trace.SpanFromContext(ctx))

resp, err := NewService(mockHydra, mockTracer, mockMonitor, mockLogger).ListClients(ctx, listReq)
resp, err := NewService(mockHydra, mockAuthz, mockTracer, mockMonitor, mockLogger).ListClients(ctx, listReq)
expectedError := new(ErrorOAuth2)
expectedError.Error = *errResp.Error
expectedError.ErrorDescription = *errResp.ErrorDescription
Expand All @@ -454,11 +468,12 @@ func TestUnmarshalClient(t *testing.T) {
mockHydra := NewMockHydraClientInterface(ctrl)
mockTracer := NewMockTracer(ctrl)
mockMonitor := monitoring.NewMockMonitorInterface(ctrl)
mockAuthz := NewMockAuthorizerInterface(ctrl)

c := hClient.NewOAuth2Client()
jsonBody, _ := c.MarshalJSON()

cc, err := NewService(mockHydra, mockTracer, mockMonitor, mockLogger).UnmarshalClient(jsonBody)
cc, err := NewService(mockHydra, mockAuthz, mockTracer, mockMonitor, mockLogger).UnmarshalClient(jsonBody)
if !reflect.DeepEqual(cc, c) {
t.Fatalf("expected flow to be %+v not %+v", c, cc)
}
Expand All @@ -475,6 +490,7 @@ func TestParseServiceError(t *testing.T) {
mockHydra := NewMockHydraClientInterface(ctrl)
mockTracer := NewMockTracer(ctrl)
mockMonitor := monitoring.NewMockMonitorInterface(ctrl)
mockAuthz := NewMockAuthorizerInterface(ctrl)

errorMsg := "error"
errorDescription := "Some error happened"
Expand All @@ -487,7 +503,7 @@ func TestParseServiceError(t *testing.T) {
Body: io.NopCloser(bytes.NewBuffer(errJson)),
StatusCode: statusCode,
}
err, _ := NewService(mockHydra, mockTracer, mockMonitor, mockLogger).parseServiceError(serviceResp)
err, _ := NewService(mockHydra, mockAuthz, mockTracer, mockMonitor, mockLogger).parseServiceError(serviceResp)

if err.Error != errorMsg {
t.Fatalf("expected error to be %+v, got: %+v", errorMsg, err.Error)
Expand Down
5 changes: 5 additions & 0 deletions pkg/identities/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import (
kClient "github.com/ory/kratos-client-go"
)

type AuthorizerInterface interface {
SetCreateIdentityEntitlements(context.Context, string) error
SetDeleteIdentityEntitlements(context.Context, string) error
}

type ServiceInterface interface {
ListIdentities(context.Context, int64, string, string) (*IdentityData, error)
GetIdentity(context.Context, string) (*IdentityData, error)
Expand Down
Loading

0 comments on commit 55d02df

Please sign in to comment.