Skip to content

Commit

Permalink
feat: add edit family of iam commands (#141)
Browse files Browse the repository at this point in the history
  • Loading branch information
JGiola authored Jan 8, 2024
1 parent a7dc817 commit 3e9edad
Show file tree
Hide file tree
Showing 23 changed files with 868 additions and 103 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- `company iam add user` command
- `company iam edit user` command
- `company iam add group` command
- `company iam add group-member` command
- `company iam edit serviceaccount` command
- `company iam edit group` command

### Changed

Expand Down
61 changes: 61 additions & 0 deletions docs/30_commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,67 @@ Available flags for the command:
- `--context`, to specify a different context from the currently selected one
- `--company-id`, to set the ID of the desired Company

#### edit user

The `company iam edit user` subcommand allows you to edit the role associated to a user in your Company.

Usage:

```sh
miactl company iam edit user [flags]
```

Available flags for the command:

- `--endpoint`, to set the Console endpoint (default is `https://console.cloud.mia-platform.eu`)
- `--certificate-authority`, to provide the path to a custom CA certificate
- `--insecure-skip-tls-verify`, to disallow the check the validity of the certificate of the remote endpoint
- `--context`, to specify a different context from the currently selected one
- `--company-id`, to set the ID of the desired Company
- `--user-id`, the id of the user to edit
- `--role`, the new Company role of the user

#### edit serviceaccount

The `company iam edit serviceaccount` subcommand allows you to edit the role associated to a service account in
your Company.

Usage:

```sh
miactl company iam edit serviceaccount [flags]
```

Available flags for the command:

- `--endpoint`, to set the Console endpoint (default is `https://console.cloud.mia-platform.eu`)
- `--certificate-authority`, to provide the path to a custom CA certificate
- `--insecure-skip-tls-verify`, to disallow the check the validity of the certificate of the remote endpoint
- `--context`, to specify a different context from the currently selected one
- `--company-id`, to set the ID of the desired Company
- `--service-account-id`, the id of the service account to edit
- `--role`, the new Company role of the service account

#### edit group

The `company iam edit group` subcommand allows you to edit the role associated to a group in your Company.

Usage:

```sh
miactl company iam edit group [flags]
```

Available flags for the command:

- `--endpoint`, to set the Console endpoint (default is `https://console.cloud.mia-platform.eu`)
- `--certificate-authority`, to provide the path to a custom CA certificate
- `--insecure-skip-tls-verify`, to disallow the check the validity of the certificate of the remote endpoint
- `--context`, to specify a different context from the currently selected one
- `--company-id`, to set the ID of the desired Company
- `--group-id`, the id of the group to edit
- `--role`, the new Company role of the group

## project

This command allows you to manage `miactl` Projects.
Expand Down
5 changes: 5 additions & 0 deletions internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type Interface interface {
Delete() *Request
Get() *Request
Post() *Request
Patch() *Request
HTTPClient() *http.Client
}

Expand Down Expand Up @@ -78,6 +79,10 @@ func (c *APIClient) Delete() *Request {
return NewRequest(c).SetVerb(http.MethodDelete)
}

func (c *APIClient) Patch() *Request {
return NewRequest(c).SetVerb(http.MethodPatch)
}

func (c *APIClient) HTTPClient() *http.Client {
return c.client
}
18 changes: 18 additions & 0 deletions internal/clioptions/clioptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,13 @@ type CLIOptions struct {
IAMRole string

UserEmail string
UserID string

UserEmails []string
GroupID string

ServiceAccountID string

BasicClientID string
BasicClientSecret string
JWTJsonPath string
Expand Down Expand Up @@ -145,11 +148,21 @@ func (o *CLIOptions) AddJWTServiceAccountFlags(flags *pflag.FlagSet) {
flags.StringVarP(&o.OutputPath, "output", "o", "", "write the service account configuration as json to a file")
}

func (o *CLIOptions) AddEditServiceAccountFlags(flags *pflag.FlagSet) {
flags.StringVarP(&o.IAMRole, "role", "r", "", "the new company role for the service account")
flags.StringVarP(&o.ServiceAccountID, "service-account-id", "", "", "the service account id to edit")
}

func (o *CLIOptions) AddNewUserFlags(flags *pflag.FlagSet) {
flags.StringVarP(&o.IAMRole, "role", "r", "", "the company role of the user")
flags.StringVarP(&o.UserEmail, "email", "", "", "the email of the user to add")
}

func (o *CLIOptions) AddEditUserFlags(flags *pflag.FlagSet) {
flags.StringVarP(&o.IAMRole, "role", "r", "", "the new company role for the user")
flags.StringVarP(&o.UserID, "user-id", "", "", "the user id to edit")
}

func (o *CLIOptions) CreateNewGroupFlags(flags *pflag.FlagSet) {
flags.StringVarP(&o.IAMRole, "role", "r", "", "the company role of the group")
}
Expand All @@ -159,6 +172,11 @@ func (o *CLIOptions) AddMemberToGroupFlags(flags *pflag.FlagSet) {
flags.StringVarP(&o.GroupID, "group-id", "", "", "the group id where to add the users")
}

func (o *CLIOptions) AddEditGroupFlags(flags *pflag.FlagSet) {
flags.StringVarP(&o.IAMRole, "role", "r", "", "the new company role for the group")
flags.StringVarP(&o.GroupID, "group-id", "", "", "the group id to edit")
}

func (o *CLIOptions) AddMarketplaceApplyFlags(cmd *cobra.Command) {
cmd.Flags().StringArrayVarP(&o.MarketplaceResourcePaths, "file-path", "f", []string{}, "paths to JSON/YAML files or folder of files containing a Marketplace item definition")
err := cmd.MarkFlagRequired("file-path")
Expand Down
1 change: 1 addition & 0 deletions internal/cmd/company/iam.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ via a group or through service accounts.`,
cmd.AddCommand(
iam.ListCmd(o),
iam.AddCmd(o),
iam.EditCmd(o),
)

return cmd
Expand Down
40 changes: 40 additions & 0 deletions internal/cmd/company/iam/edit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright Mia srl
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package iam

import (
"github.com/mia-platform/miactl/internal/clioptions"
"github.com/mia-platform/miactl/internal/cmd/company/iam/group"
"github.com/mia-platform/miactl/internal/cmd/company/iam/serviceaccount"
"github.com/mia-platform/miactl/internal/cmd/company/iam/user"
"github.com/spf13/cobra"
)

func EditCmd(options *clioptions.CLIOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "edit",
Short: "Edit an IAM entity in a company",
Long: "Edit an IAM entity in a company",
}

cmd.AddCommand(
user.EditCmd(options),
serviceaccount.EditCmd(options),
group.EditCmd(options),
)

return cmd
}
17 changes: 4 additions & 13 deletions internal/cmd/company/iam/group/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,13 @@ func AddCmd(options *clioptions.CLIOptions) *cobra.Command {
client, err := client.APIClientForConfig(restConfig)
cobra.CheckErr(err)

err = createNewGroup(cmd.Context(), client, restConfig.CompanyID, args[0], resources.ServiceAccountRole(options.IAMRole))
err = createNewGroup(cmd.Context(), client, restConfig.CompanyID, args[0], resources.IAMRole(options.IAMRole))
cobra.CheckErr(err)
},
}

options.CreateNewGroupFlags(cmd.Flags())
err := cmd.RegisterFlagCompletionFunc("role", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{
resources.ServiceAccountRoleGuest.String(),
resources.ServiceAccountRoleReporter.String(),
resources.ServiceAccountRoleDeveloper.String(),
resources.ServiceAccountRoleMaintainer.String(),
resources.ServiceAccountRoleProjectAdmin.String(),
resources.ServiceAccountRoleCompanyOwner.String(),
}, cobra.ShellCompDirectiveDefault
})
err := cmd.RegisterFlagCompletionFunc("role", resources.IAMRoleCompletion)

if err != nil {
// we panic here because if we reach here, something nasty is happening in flag autocomplete registration
Expand All @@ -67,8 +58,8 @@ func AddCmd(options *clioptions.CLIOptions) *cobra.Command {
return cmd
}

func createNewGroup(ctx context.Context, client *client.APIClient, companyID, groupName string, role resources.ServiceAccountRole) error {
if !resources.IsValidServiceAccountRole(role) {
func createNewGroup(ctx context.Context, client *client.APIClient, companyID, groupName string, role resources.IAMRole) error {
if !resources.IsValidIAMRole(role) {
return fmt.Errorf("invalid service account role %s", role)
}

Expand Down
12 changes: 6 additions & 6 deletions internal/cmd/company/iam/group/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,41 +32,41 @@ func TestCreateGroup(t *testing.T) {
testCases := map[string]struct {
server *httptest.Server
companyID string
role resources.ServiceAccountRole
role resources.IAMRole
groupName string
expectErr bool
}{
"create group": {
server: addUserTestServer(t),
companyID: "success",
role: resources.ServiceAccountRoleGuest,
role: resources.IAMRoleGuest,
groupName: "group-name",
},
"missing company": {
server: addUserTestServer(t),
companyID: "",
role: resources.ServiceAccountRoleGuest,
role: resources.IAMRoleGuest,
groupName: "group-name",
expectErr: true,
},
"missing group name": {
server: addUserTestServer(t),
companyID: "success",
role: resources.ServiceAccountRoleGuest,
role: resources.IAMRoleGuest,
groupName: "",
expectErr: true,
},
"wrong role": {
server: addUserTestServer(t),
companyID: "succes",
role: resources.ServiceAccountRole("example"),
role: resources.IAMRole("example"),
groupName: "group-name",
expectErr: true,
},
"error from backend": {
server: addUserTestServer(t),
companyID: "fail",
role: resources.ServiceAccountRoleCompanyOwner,
role: resources.IAMRoleCompanyOwner,
groupName: "group-name",
expectErr: true,
},
Expand Down
99 changes: 99 additions & 0 deletions internal/cmd/company/iam/group/edit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright Mia srl
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package group

import (
"context"
"fmt"

"github.com/mia-platform/miactl/internal/client"
"github.com/mia-platform/miactl/internal/clioptions"
"github.com/mia-platform/miactl/internal/resources"
"github.com/spf13/cobra"
)

const (
editGroupRoleTemplate = "/api/companies/%s/groups/%s"
)

func EditCmd(options *clioptions.CLIOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "group",
Short: "Edit a group in a company",
Long: "Edit a group in a company",

Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
restConfig, err := options.ToRESTConfig()
cobra.CheckErr(err)
client, err := client.APIClientForConfig(restConfig)
cobra.CheckErr(err)

err = editCompanyGroup(cmd.Context(), client, restConfig.CompanyID, options.GroupID, resources.IAMRole(options.IAMRole))
cobra.CheckErr(err)
},
}

options.AddEditGroupFlags(cmd.Flags())
err := cmd.RegisterFlagCompletionFunc("role", resources.IAMRoleCompletion)

if err != nil {
// we panic here because if we reach here, something nasty is happening in flag autocomplete registration
panic(err)
}

return cmd
}

func editCompanyGroup(ctx context.Context, client *client.APIClient, companyID, groupID string, role resources.IAMRole) error {
if !resources.IsValidIAMRole(role) {
return fmt.Errorf("invalid service account role %s", role)
}

if len(companyID) == 0 {
return fmt.Errorf("company id is required, please set it via flag or context")
}

if len(groupID) == 0 {
return fmt.Errorf("the group id is required")
}

payload := resources.EditIAMRole{
Role: role,
}

body, err := resources.EncodeResourceToJSON(payload)
if err != nil {
return fmt.Errorf("failed to encode request body: %w", err)
}

resp, err := client.
Patch().
APIPath(fmt.Sprintf(editGroupRoleTemplate, companyID, groupID)).
Body(body).
Do(ctx)

if err != nil {
return err
}

if err := resp.Error(); err != nil {
return err
}

fmt.Printf("group %s role successfully updated\n", groupID)
return nil
}
Loading

0 comments on commit 3e9edad

Please sign in to comment.