diff --git a/internal/jimm/cloudcredential.go b/internal/jimm/cloudcredential.go index 9e710a982..5691a2c06 100644 --- a/internal/jimm/cloudcredential.go +++ b/internal/jimm/cloudcredential.go @@ -342,6 +342,9 @@ func (j *JIMM) GetCloudCredentialAttributes(ctx context.Context, user *openfga.U err = errors.E(op, err) return } + if len(attrs) == 0 { + return map[string]string{}, nil, nil + } if hidden { return @@ -377,8 +380,5 @@ func (j *JIMM) getCloudCredentialAttributes(ctx context.Context, cred *dbmodel.C if err != nil { return nil, errors.E(op, err) } - if len(attr) == 0 && cred.AuthType != "empty" { - return nil, errors.E(op, errors.CodeNotFound, "cloud-credential attributes not found") - } return attr, nil } diff --git a/internal/jimm/cloudcredential_test.go b/internal/jimm/cloudcredential_test.go index 775b48d23..4e4151e4d 100644 --- a/internal/jimm/cloudcredential_test.go +++ b/internal/jimm/cloudcredential_test.go @@ -5,6 +5,7 @@ package jimm_test import ( "context" "database/sql" + "fmt" "sync" "testing" "time" @@ -1538,6 +1539,10 @@ cloud-credentials: client-id: 1234 private-key: super-secret project-id: 5678 +- name: cred-2 + cloud: test-cloud + owner: bob@canonical.com + auth-type: certificate users: - username: alice@canonical.com controller-access: superuser @@ -1549,6 +1554,7 @@ var getCloudCredentialAttributesTests = []struct { username string hidden bool jimmAdmin bool + cred string expectAttributes map[string]string expectRedacted []string expectError string @@ -1557,16 +1563,25 @@ var getCloudCredentialAttributesTests = []struct { name: "OwnerNoHidden", username: "bob@canonical.com", jimmAdmin: true, + cred: "cred-1", expectAttributes: map[string]string{ "client-email": "bob@example.com", "client-id": "1234", "project-id": "5678", }, expectRedacted: []string{"private-key"}, +}, { + name: "OwnerNoAttributes", + username: "bob@canonical.com", + jimmAdmin: true, + cred: "cred-2", + expectAttributes: map[string]string{}, + expectRedacted: nil, }, { name: "OwnerWithHidden", username: "bob@canonical.com", hidden: true, + cred: "cred-1", expectAttributes: map[string]string{ "client-email": "bob@example.com", "client-id": "1234", @@ -1577,6 +1592,7 @@ var getCloudCredentialAttributesTests = []struct { name: "SuperUserNoHidden", username: "alice@canonical.com", jimmAdmin: true, + cred: "cred-1", expectAttributes: map[string]string{ "client-email": "bob@example.com", "client-id": "1234", @@ -1588,11 +1604,13 @@ var getCloudCredentialAttributesTests = []struct { username: "alice@canonical.com", hidden: true, jimmAdmin: true, + cred: "cred-1", expectError: `unauthorized`, expectErrorCode: errors.CodeUnauthorized, }, { name: "OtherUserUnauthorized", username: "charlie@canonical.com", + cred: "cred-1", expectError: `unauthorized`, expectErrorCode: errors.CodeUnauthorized, }} @@ -1623,7 +1641,8 @@ func TestGetCloudCredentialAttributes(t *testing.T) { env.PopulateDBAndPermissions(c, j.ResourceTag(), j.Database, client) u := env.User("bob@canonical.com").DBObject(c, j.Database) userBob := openfga.NewUser(&u, client) - cred, err := j.GetCloudCredential(ctx, userBob, names.NewCloudCredentialTag("test-cloud/bob@canonical.com/cred-1")) + credTag := fmt.Sprintf("test-cloud/bob@canonical.com/%s", test.cred) + cred, err := j.GetCloudCredential(ctx, userBob, names.NewCloudCredentialTag(credTag)) c.Assert(err, qt.IsNil) u = env.User(test.username).DBObject(c, j.Database) @@ -1714,7 +1733,7 @@ func TestCloudCredentialAttributeStore(t *testing.T) { // Update to an "empty" credential args.Credential.AuthType = "empty" - args.Credential.Attributes = nil + args.Credential.Attributes = map[string]string{} _, err = j.UpdateCloudCredential(ctx, user, args) c.Assert(err, qt.IsNil) diff --git a/internal/jujuapi/cloud_test.go b/internal/jujuapi/cloud_test.go index 58d4144e3..e2fa8a3b8 100644 --- a/internal/jujuapi/cloud_test.go +++ b/internal/jujuapi/cloud_test.go @@ -729,6 +729,33 @@ func (s *cloudSuite) TestCredentialContents(c *gc.C) { }}) } +func (s *cloudSuite) TestCredentialContentsWithEmptyAttributes(c *gc.C) { + conn := s.open(c, nil, "test") + defer conn.Close() + client := cloudapi.NewClient(conn) + credentialTag := names.NewCloudCredentialTag(jimmtest.TestCloudName + "/test@canonical.com/cred3") + err := client.AddCredential( + credentialTag.String(), + cloud.NewCredential( + "certificate", + nil, + ), + ) + c.Assert(err, gc.Equals, nil) + creds, err := client.CredentialContents(jimmtest.TestCloudName, "cred3", false) + c.Assert(err, gc.Equals, nil) + c.Assert(creds, jc.DeepEquals, []jujuparams.CredentialContentResult{{ + Result: &jujuparams.ControllerCredentialInfo{ + Content: jujuparams.CredentialContent{ + Name: "cred3", + Cloud: jimmtest.TestCloudName, + AuthType: "certificate", + Attributes: nil, + }, + }, + }}) +} + func (s *cloudSuite) TestRemoveCloud(c *gc.C) { conn := s.open(c, nil, "test") defer conn.Close()