-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CSS-6763 Introduce addServiceAccount method (#1127)
* Introduce AddServiceAccount method * Fixed auth model and added tests * Update copyright date * PR changes * Correctly rename field * Check if user has permission over service account * Update service_account_test.go
- Loading branch information
Showing
9 changed files
with
207 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// Copyright 2024 Canonical Ltd. | ||
|
||
package jimm | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/canonical/jimm/internal/errors" | ||
"github.com/canonical/jimm/internal/openfga" | ||
ofganames "github.com/canonical/jimm/internal/openfga/names" | ||
jimmnames "github.com/canonical/jimm/pkg/names" | ||
) | ||
|
||
// AddServiceAccount checks that no one owns the service account yet | ||
// and then adds a relation between the logged in user and the service account. | ||
func (j *JIMM) AddServiceAccount(ctx context.Context, u *openfga.User, clientId string) error { | ||
op := errors.Op("jimm.AddServiceAccount") | ||
svcTag := jimmnames.NewServiceAccountTag(clientId) | ||
key := openfga.Tuple{ | ||
Relation: ofganames.AdministratorRelation, | ||
Target: ofganames.ConvertTag(svcTag), | ||
} | ||
keyWithUser := key | ||
keyWithUser.Object = ofganames.ConvertTag(u.ResourceTag()) | ||
|
||
ok, err := j.OpenFGAClient.CheckRelation(ctx, keyWithUser, false) | ||
if err != nil { | ||
return errors.E(op, err) | ||
} | ||
// If the user already has administration permission over the | ||
// service account then return early. | ||
if ok { | ||
return nil | ||
} | ||
|
||
tuples, _, err := j.OpenFGAClient.ReadRelatedObjects(ctx, key, 10, "") | ||
if err != nil { | ||
return errors.E(op, err) | ||
} | ||
if len(tuples) > 0 { | ||
return errors.E(op, "service account already owned") | ||
} | ||
addTuple := openfga.Tuple{ | ||
Object: ofganames.ConvertTag(u.ResourceTag()), | ||
Relation: ofganames.AdministratorRelation, | ||
Target: ofganames.ConvertTag(svcTag), | ||
} | ||
err = j.AuthorizationClient().AddRelation(ctx, addTuple) | ||
if err != nil { | ||
return errors.E(op, err) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// Copyright 2024 Canonical Ltd. | ||
|
||
package jimm_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
qt "github.com/frankban/quicktest" | ||
|
||
"github.com/canonical/jimm/internal/dbmodel" | ||
"github.com/canonical/jimm/internal/jimm" | ||
"github.com/canonical/jimm/internal/jimmtest" | ||
"github.com/canonical/jimm/internal/openfga" | ||
) | ||
|
||
func TestAddServiceAccount(t *testing.T) { | ||
c := qt.New(t) | ||
|
||
ctx := context.Background() | ||
client, _, _, err := jimmtest.SetupTestOFGAClient(c.Name()) | ||
c.Assert(err, qt.IsNil) | ||
j := &jimm.JIMM{ | ||
OpenFGAClient: client, | ||
} | ||
c.Assert(err, qt.IsNil) | ||
user := openfga.NewUser( | ||
&dbmodel.User{ | ||
Username: "bob@external", | ||
DisplayName: "Bob", | ||
}, | ||
client, | ||
) | ||
clientID := "39caae91-b914-41ae-83f8-c7b86ca5ad5a" | ||
err = j.AddServiceAccount(ctx, user, clientID) | ||
c.Assert(err, qt.IsNil) | ||
err = j.AddServiceAccount(ctx, user, clientID) | ||
c.Assert(err, qt.IsNil) | ||
userAlice := openfga.NewUser( | ||
&dbmodel.User{ | ||
Username: "alive@external", | ||
DisplayName: "Alice", | ||
}, | ||
client, | ||
) | ||
err = j.AddServiceAccount(ctx, userAlice, clientID) | ||
c.Assert(err, qt.ErrorMatches, "service account already owned") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// Copyright 2024 canonical. | ||
|
||
package jujuapi | ||
|
||
import ( | ||
"context" | ||
|
||
apiparams "github.com/canonical/jimm/api/params" | ||
"github.com/canonical/jimm/internal/errors" | ||
jimmnames "github.com/canonical/jimm/pkg/names" | ||
) | ||
|
||
// service_acount contains the primary RPC commands for handling service accounts within JIMM via the JIMM facade itself. | ||
|
||
// AddGroup creates a group within JIMMs DB for reference by OpenFGA. | ||
func (r *controllerRoot) AddServiceAccount(ctx context.Context, req apiparams.AddServiceAccountRequest) error { | ||
const op = errors.Op("jujuapi.AddGroup") | ||
|
||
if !jimmnames.IsValidServiceAccountId(req.ClientID) { | ||
return errors.E(op, errors.CodeBadRequest, "invalid client ID") | ||
} | ||
|
||
return r.jimm.AddServiceAccount(ctx, r.user, req.ClientID) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Copyright 2024 Canonical Ltd. | ||
|
||
package jujuapi_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/canonical/jimm/api/params" | ||
"github.com/canonical/jimm/internal/jimmtest" | ||
"github.com/canonical/jimm/internal/jujuapi" | ||
"github.com/canonical/jimm/internal/openfga" | ||
qt "github.com/frankban/quicktest" | ||
) | ||
|
||
func TestAddServiceAccount(t *testing.T) { | ||
c := qt.New(t) | ||
|
||
tests := []struct { | ||
about string | ||
addServiceAccount func(ctx context.Context, user *openfga.User, clientID string) error | ||
args params.AddServiceAccountRequest | ||
expectedError string | ||
}{{ | ||
about: "Valid client ID", | ||
addServiceAccount: func(ctx context.Context, user *openfga.User, clientID string) error { | ||
return nil | ||
}, | ||
args: params.AddServiceAccountRequest{ | ||
ClientID: "fca1f605-736e-4d1f-bcd2-aecc726923be", | ||
}, | ||
}, { | ||
about: "Invalid Client ID", | ||
addServiceAccount: func(ctx context.Context, user *openfga.User, clientID string) error { | ||
return nil | ||
}, | ||
args: params.AddServiceAccountRequest{ | ||
ClientID: "_123_", | ||
}, | ||
expectedError: "invalid client ID", | ||
}} | ||
|
||
for _, test := range tests { | ||
test := test | ||
c.Run(test.about, func(c *qt.C) { | ||
jimm := &jimmtest.JIMM{ | ||
AddServiceAccount_: test.addServiceAccount, | ||
} | ||
cr := jujuapi.NewControllerRoot(jimm, jujuapi.Params{}) | ||
|
||
err := cr.AddServiceAccount(context.Background(), test.args) | ||
if test.expectedError == "" { | ||
c.Assert(err, qt.IsNil) | ||
} else { | ||
c.Assert(err, qt.ErrorMatches, test.expectedError) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters