Skip to content

Commit 3c3d02a

Browse files
authored
Merge branch 'scaleway:master' into master
2 parents 4dbbe4d + 6eb14c1 commit 3c3d02a

8 files changed

+352
-26
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ scw-cli-v2-version
99

1010
# To avoid having differences in case you use a different shell than bash while recording the goldens
1111
docs/commands/autocomplete.md
12+
13+
scw

Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
build:
2+
./scripts/build.sh
3+
4+
lint:
5+
./scripts/lint.sh
6+
7+
test:
8+
./scripts/test.sh
9+
10+
fmt:
11+
golangci-lint run --fix ./...

internal/namespaces/iam/v1alpha1/custom_iam.go

Lines changed: 87 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package iam
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"reflect"
78

@@ -12,9 +13,9 @@ import (
1213
)
1314

1415
type apiKeyResponse struct {
15-
APIKey *iam.APIKey
16-
UserType string `json:"user_type"`
17-
Policies map[string][]string `json:"policies"`
16+
APIKey *iam.APIKey
17+
EntityType string `json:"entity_type"`
18+
Policies map[string][]string `json:"policies"`
1819
}
1920
type iamGetAPIKeyArgs struct {
2021
AccessKey string
@@ -31,6 +32,76 @@ func WithPolicies(withPolicies bool) apiKeyOptions {
3132
}
3233
}
3334

35+
type userEntity struct {
36+
UserID string
37+
}
38+
39+
type applicationEntity struct {
40+
ApplicationID string
41+
}
42+
43+
type entity interface {
44+
entityType(ctx context.Context, api *iam.API) (string, error)
45+
getPolicies(ctx context.Context, api *iam.API) ([]*iam.Policy, error)
46+
}
47+
48+
func (u userEntity) entityType(ctx context.Context, api *iam.API) (string, error) {
49+
user, err := api.GetUser(&iam.GetUserRequest{
50+
UserID: u.UserID,
51+
}, scw.WithContext(ctx))
52+
if err != nil {
53+
return "", err
54+
}
55+
56+
return string(user.Type), nil
57+
}
58+
59+
func (a applicationEntity) entityType(ctx context.Context, api *iam.API) (string, error) {
60+
return "application", nil
61+
}
62+
63+
func buildEntity(apiKey *iam.APIKey) (entity, error) {
64+
if apiKey == nil {
65+
return nil, errors.New("invalid API key")
66+
}
67+
if apiKey.UserID != nil {
68+
return userEntity{UserID: *apiKey.UserID}, nil
69+
}
70+
if apiKey.ApplicationID != nil {
71+
return applicationEntity{ApplicationID: *apiKey.ApplicationID}, nil
72+
}
73+
74+
return nil, errors.New("invalid API key")
75+
}
76+
77+
func (u userEntity) getPolicies(ctx context.Context, api *iam.API) ([]*iam.Policy, error) {
78+
policies, err := api.ListPolicies(&iam.ListPoliciesRequest{
79+
UserIDs: []string{u.UserID},
80+
}, scw.WithContext(ctx), scw.WithAllPages())
81+
if err != nil {
82+
return nil, err
83+
}
84+
if policies == nil {
85+
return nil, errors.New("no policies found")
86+
}
87+
88+
return policies.Policies, nil
89+
}
90+
91+
func (a applicationEntity) getPolicies(ctx context.Context, api *iam.API) ([]*iam.Policy, error) {
92+
policies, err := api.ListPolicies(&iam.ListPoliciesRequest{
93+
ApplicationIDs: []string{a.ApplicationID},
94+
}, scw.WithContext(ctx), scw.WithAllPages())
95+
if err != nil {
96+
return nil, err
97+
}
98+
if policies == nil {
99+
return nil, errors.New("no policies found")
100+
}
101+
102+
return policies.Policies, nil
103+
}
104+
34105
func getApiKey(
35106
ctx context.Context,
36107
api *iam.API,
@@ -45,40 +116,34 @@ func getApiKey(
45116
return response, err
46117
}
47118

48-
user, err := api.GetUser(&iam.GetUserRequest{
49-
UserID: *apiKey.UserID,
50-
}, scw.WithContext(ctx))
119+
entity, err := buildEntity(apiKey)
120+
if err != nil {
121+
return response, err
122+
}
123+
124+
entityType, err := entity.entityType(ctx, api)
51125
if err != nil {
52126
return response, err
53127
}
54128

55129
response.APIKey = apiKey
56-
response.UserType = string(user.Type)
130+
response.EntityType = entityType
57131

58-
if user.Type == iam.UserTypeOwner {
59-
response.UserType = fmt.Sprintf(
60-
"%s (owner has all permissions over the organization)",
61-
user.Type,
62-
)
132+
if entityType == string(iam.UserTypeOwner) {
133+
response.EntityType = entityType + " (owner has all permissions over the organization)"
63134

64135
return response, nil
65136
}
66137

67138
if options.WithPolicies {
68-
listPolicyRequest := &iam.ListPoliciesRequest{
69-
UserIDs: []string{*apiKey.UserID},
70-
}
71-
policies, err := api.ListPolicies(
72-
listPolicyRequest,
73-
scw.WithAllPages(),
74-
scw.WithContext(ctx),
75-
)
139+
policies, err := entity.getPolicies(ctx, api)
76140
if err != nil {
77141
return response, err
78142
}
143+
79144
// Build a map of policies -> [rules...]
80145
policyMap := map[string][]string{}
81-
for _, policy := range policies.Policies {
146+
for _, policy := range policies {
82147
rules, err := api.ListRules(
83148
&iam.ListRulesRequest{
84149
PolicyID: policy.ID,
@@ -107,7 +172,7 @@ func apiKeyMarshalerFunc(i any, opt *human.MarshalOpt) (string, error) {
107172

108173
opt.Sections = []*human.MarshalSection{
109174
{
110-
FieldName: "UserType",
175+
FieldName: "EntityType",
111176
},
112177
{
113178
FieldName: "APIKey",

internal/namespaces/iam/v1alpha1/custom_iam_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package iam_test
22

33
import (
4+
"os"
45
"testing"
56

67
"github.com/scaleway/scaleway-cli/v2/core"
@@ -10,6 +11,10 @@ import (
1011
)
1112

1213
func Test_iamAPIKeyGet(t *testing.T) {
14+
if isNightly := os.Getenv("SLACK_WEBHOOK_NIGHTLY"); isNightly != "" {
15+
t.Skip()
16+
}
17+
1318
commands := iam.GetCommands()
1419
commands.Merge(account.GetCommands())
1520

@@ -50,6 +55,18 @@ func Test_iamAPIKeyGet(t *testing.T) {
5055
return apiKeys[0].AccessKey
5156
}
5257

58+
applicationResulter := func(result any) any {
59+
applications := result.([]*iamSdk.Application)
60+
if applications == nil {
61+
panic("applications is nil")
62+
}
63+
if len(applications) == 0 {
64+
panic("no application found")
65+
}
66+
67+
return applications[0].ID
68+
}
69+
5370
t.Run("GetOwnerAPIKey", core.Test(&core.TestConfig{
5471
Commands: commands,
5572
BeforeFunc: core.BeforeFuncCombine(
@@ -92,4 +109,25 @@ func Test_iamAPIKeyGet(t *testing.T) {
92109
core.TestCheckExitCode(0),
93110
),
94111
}))
112+
113+
t.Run("GetApplicationAPIKey", core.Test(&core.TestConfig{
114+
Commands: commands,
115+
BeforeFunc: core.BeforeFuncCombine(
116+
core.ExecStoreBeforeCmdWithResulter(
117+
"application",
118+
"scw iam application list",
119+
applicationResulter,
120+
),
121+
core.ExecStoreBeforeCmdWithResulter(
122+
"applicationAPIKey",
123+
"scw iam api-key list bearer-id={{ .application }}",
124+
apiKeyResulter,
125+
),
126+
),
127+
Cmd: `scw iam api-key get {{ .applicationAPIKey }}`,
128+
Check: core.TestCheckCombine(
129+
core.TestCheckGolden(),
130+
core.TestCheckExitCode(0),
131+
),
132+
}))
95133
}

0 commit comments

Comments
 (0)