Skip to content
This repository has been archived by the owner on May 6, 2022. It is now read-only.

Commit

Permalink
add support for member types
Browse files Browse the repository at this point in the history
  • Loading branch information
srinandan committed Jun 14, 2021
1 parent 02079f1 commit 4e590fe
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 58 deletions.
40 changes: 22 additions & 18 deletions apiclient/iam.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ func createAllRoleBindings(name string) []roleBinding {
return bindings
}

//SetIAMServiceAccount create a new IAM SA with the necessary roles for an Apigee Env
func SetIAMServiceAccount(serviceAccountName string, iamRole string) (err error) {
//SetIAMPermission set permissions for a member on an Apigee Env
func SetIAMPermission(memberName string, iamRole string, memberType string) (err error) {
var role string

switch iamRole {
Expand Down Expand Up @@ -254,7 +254,7 @@ func SetIAMServiceAccount(serviceAccountName string, iamRole string) (err error)
for i, binding := range getIamPolicy.Bindings {
if binding.Role == role {
//found members with the role already, add the new SA to the role
getIamPolicy.Bindings[i].Members = append(binding.Members, "serviceAccount:"+serviceAccountName)
getIamPolicy.Bindings[i].Members = append(binding.Members, memberType+":"+memberName)
foundRole = true
}
}
Expand All @@ -263,7 +263,7 @@ func SetIAMServiceAccount(serviceAccountName string, iamRole string) (err error)
if !foundRole {
binding := roleBinding{}
binding.Role = role
binding.Members = append(binding.Members, "serviceAccount:"+serviceAccountName)
binding.Members = append(binding.Members, memberType+":"+memberName)
getIamPolicy.Bindings = append(getIamPolicy.Bindings, binding)
}

Expand All @@ -284,8 +284,8 @@ func SetIAMServiceAccount(serviceAccountName string, iamRole string) (err error)
return err
}

//RemoveIAMServiceAccount removes/unbinds IAM SA from all roles for an Apigee Env
func RemoveIAMServiceAccount(serviceAccountName string, iamRole string) (err error) {
//RemoveIAMPermission removes/unbinds IAM permission from all roles for an Apigee Env
func RemoveIAMPermission(memberName string, iamRole string) (err error) {
u, _ := url.Parse(BaseURL)
u.Path = path.Join(u.Path, GetApigeeOrg(), "environments", GetApigeeEnv()+":getIamPolicy")
getIamPolicyBody, err := HttpClient(false, u.String())
Expand Down Expand Up @@ -314,12 +314,16 @@ func RemoveIAMServiceAccount(serviceAccountName string, iamRole string) (err err
} else if numBindings == 1 { //there is only 1 binding
clilog.Info.Printf("comparing %s and %s\n", getIamPolicy.Bindings[0].Role, iamRole)
if getIamPolicy.Bindings[0].Role == iamRole {
if len(getIamPolicy.Bindings[0].Members) > 1 { //more than one memeber in the role
if len(getIamPolicy.Bindings[0].Members) > 1 { //more than one member in the role
removeIamPolicy.Policy.Etag = getIamPolicy.Etag
//create a new role binding
removeIamPolicy.Policy.Bindings = append(removeIamPolicy.Policy.Bindings, roleBinding{})
//copy the role
removeIamPolicy.Policy.Bindings[0].Role = getIamPolicy.Bindings[0].Role
//copy other members
for _, member := range getIamPolicy.Bindings[0].Members {
clilog.Info.Printf("comparing %s and %s\n", serviceAccountName, member)
if member == serviceAccountName {
clilog.Info.Printf("comparing %s and %s\n", memberName, member)
if member == memberName {
clilog.Info.Println("found member")
foundMember = true
//don't include this member
Expand All @@ -328,14 +332,14 @@ func RemoveIAMServiceAccount(serviceAccountName string, iamRole string) (err err
}
}
if !foundMember {
return fmt.Errorf("member %s not set for role %s in environment %s", serviceAccountName, iamRole, GetApigeeEnv())
return fmt.Errorf("member %s not set for role %s in environment %s", memberName, iamRole, GetApigeeEnv())
}
} else { //there is one member, one role
if getIamPolicy.Bindings[0].Members[0] == serviceAccountName {
clilog.Info.Printf("comparing %s and %s\n", getIamPolicy.Bindings[0].Members[0], serviceAccountName)
if getIamPolicy.Bindings[0].Members[0] == memberName {
clilog.Info.Printf("comparing %s and %s\n", getIamPolicy.Bindings[0].Members[0], memberName)
removeIamPolicy.Policy.Etag = getIamPolicy.Etag
} else {
return fmt.Errorf("member %s not set for role %s in environment %s", serviceAccountName, iamRole, GetApigeeEnv())
return fmt.Errorf("member %s not set for role %s in environment %s", memberName, iamRole, GetApigeeEnv())
}
}
} else {
Expand All @@ -349,21 +353,21 @@ func RemoveIAMServiceAccount(serviceAccountName string, iamRole string) (err err
if binding.Role == iamRole {
if len(binding.Members) > 1 { //there is more than one member in the role
for _, member := range binding.Members {
clilog.Info.Printf("comparing %s and %s\n", member, serviceAccountName)
if member == serviceAccountName { //remove the member
clilog.Info.Printf("comparing %s and %s\n", member, memberName)
if member == memberName { //remove the member
foundMember = true
} else {
members = append(members, member)
}
}
if !foundMember {
return fmt.Errorf("member %s not set for role %s in environment %s", serviceAccountName, iamRole, GetApigeeEnv())
return fmt.Errorf("member %s not set for role %s in environment %s", memberName, iamRole, GetApigeeEnv())
}
} else { //there is only one member in the role
if binding.Members[0] == serviceAccountName {
if binding.Members[0] == memberName {
foundMember = true
} else {
return fmt.Errorf("member %s not set for role %s in environment %s", serviceAccountName, iamRole, GetApigeeEnv())
return fmt.Errorf("member %s not set for role %s in environment %s", memberName, iamRole, GetApigeeEnv())
}
}
copyRoleBinding := roleBinding{}
Expand Down
27 changes: 23 additions & 4 deletions client/env/iam.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@
package env

import (
"fmt"
"net/url"
"path"

"github.com/srinandan/apigeecli/apiclient"
)

var validMemberTypes = []string{"serviceAccount", "group", "user", "domain"}

//GetIAM
func GetIAM() (respBody []byte, err error) {
u, _ := url.Parse(apiclient.BaseURL)
Expand All @@ -30,13 +33,20 @@ func GetIAM() (respBody []byte, err error) {
}

//SetIAM
func SetIAM(serviceAccountName string, permission string) (err error) {
return apiclient.SetIAMServiceAccount(serviceAccountName, permission)
func SetIAM(memberName string, permission string, memberType string) (err error) {
if !isValidMemberType(memberType) {
return fmt.Errorf("Invalid memberType. Valid types are %v", validMemberTypes)
}
return apiclient.SetIAMPermission(memberName, permission, memberType)
}

//RemoveIAM
func RemoveIAM(serviceAccountName string, role string) (err error) {
return apiclient.RemoveIAMServiceAccount(serviceAccountName, role)
func RemoveIAM(memberName string, role string, memberType string) (err error) {
if !isValidMemberType(memberType) {
return fmt.Errorf("Invalid memberType. Valid types are %v", validMemberTypes)
}
member := memberType + ":" + memberName
return apiclient.RemoveIAMPermission(member, role)
}

//TestIAM
Expand All @@ -48,3 +58,12 @@ func TestIAM(resource string, verb string) (respBody []byte, err error) {
respBody, err = apiclient.HttpClient(apiclient.GetPrintOutput(), u.String(), payload)
return respBody, err
}

func isValidMemberType(memberType string) bool {
for _, validMember := range validMemberTypes {
if memberType == validMember {
return true
}
}
return false
}
25 changes: 17 additions & 8 deletions client/sync/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func Reset() (respBody []byte, err error) {
}

//Set
func Set(identity string) (respBody []byte, err error) {
func Set(identity interface{}) (respBody []byte, err error) {

u, _ := url.Parse(apiclient.BaseURL)
u.Path = path.Join(u.Path, apiclient.GetApigeeOrg()+":getSyncAuthorization")
Expand All @@ -74,16 +74,25 @@ func Set(identity string) (respBody []byte, err error) {
return respBody, err
}

identity = validate(identity)

for _, setIdentity := range response.Identities {
if identity == setIdentity {
return respBody, fmt.Errorf("identity %s already set", identity)
switch param := identity.(type) {
case []string:
var syncIdentities []string
for _, syncIdentity := range param {
syncIdentities = append(syncIdentities, validate(syncIdentity))
}
response.Identities = append(response.Identities, syncIdentities...)
case string:
param = validate(param)
for _, setIdentity := range response.Identities {
if param == setIdentity {
return respBody, fmt.Errorf("identity %s already set", param)
}
}
response.Identities = append(response.Identities, param)
default:
return nil, fmt.Errorf("unsupported identity type")
}

response.Identities = append(response.Identities, identity)

identities := iAMIdentities{}
identities.Identities = response.Identities
payload, err := json.Marshal(&identities)
Expand Down
2 changes: 1 addition & 1 deletion cmd/env/iam.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var IamCmd = &cobra.Command{
Long: "Manage IAM permissions for the environment",
}

var serviceAccountName, role string
var memberName, role, memberType string

func init() {

Expand Down
8 changes: 5 additions & 3 deletions cmd/env/removerole.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,23 @@ var RemoveRoleCmd = &cobra.Command{
return apiclient.SetApigeeOrg(org)
},
RunE: func(cmd *cobra.Command, args []string) (err error) {
err = environments.RemoveIAM(serviceAccountName, role)
err = environments.RemoveIAM(memberName, role, memberType)
if err != nil {
return err
}
fmt.Printf("Service account %s removed access to role %s\n", serviceAccountName, role)
fmt.Printf("Member %s (type = %s) removed access to role %s\n", memberName, memberType, role)
return nil
},
}

func init() {

RemoveRoleCmd.Flags().StringVarP(&serviceAccountName, "name", "n",
RemoveRoleCmd.Flags().StringVarP(&memberName, "name", "n",
"", "Service Account Name")
RemoveRoleCmd.Flags().StringVarP(&role, "role", "r",
"", "IAM Role")
RemoveRoleCmd.Flags().StringVarP(&memberType, "memberType", "m",
"serviceAccount", "memberType must be serviceAccount, user or group")

_ = RemoveRoleCmd.MarkFlagRequired("name")
_ = RemoveRoleCmd.MarkFlagRequired("role")
Expand Down
14 changes: 8 additions & 6 deletions cmd/env/setax.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,28 @@ import (
//Cmd to manage tracing of apis
var SetAxCmd = &cobra.Command{
Use: "setax",
Short: "Set Analytics Agent role for a SA on an environment",
Long: "Set Analytics Agent role for a SA an Environment",
Short: "Set Analytics Agent role for a member on an environment",
Long: "Set Analytics Agent role for a member an Environment",
Args: func(cmd *cobra.Command, args []string) (err error) {
apiclient.SetApigeeEnv(environment)
return apiclient.SetApigeeOrg(org)
},
RunE: func(cmd *cobra.Command, args []string) (err error) {
err = environments.SetIAM(serviceAccountName, "analytics")
err = environments.SetIAM(memberName, "analytics", memberType)
if err != nil {
return err
}
fmt.Printf("Service account %s granted access to Apigee Analytics Viewer role\n", serviceAccountName)
fmt.Printf("Member %s granted access to Apigee Analytics Viewer role\n", memberName)
return nil
},
}

func init() {

SetAxCmd.Flags().StringVarP(&serviceAccountName, "name", "n",
"", "Service Account Name")
SetAxCmd.Flags().StringVarP(&memberName, "name", "n",
"", "Member Name, example Service Account Name")
SetAxCmd.Flags().StringVarP(&memberType, "memberType", "m",
"serviceAccount", "memberType must be serviceAccount, user or group")

_ = SetAxCmd.MarkFlagRequired("name")
}
14 changes: 8 additions & 6 deletions cmd/env/setcustom.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import (
//SetCustCmd to manage custom roles for an env
var SetCustCmd = &cobra.Command{
Use: "setcustom",
Short: "Set a custom role for a SA on an environment",
Long: "Set a custom role for a SA on an environment",
Short: "Set a custom role for a member on an environment",
Long: "Set a custom role for a member on an environment",
Args: func(cmd *cobra.Command, args []string) (err error) {
apiclient.SetApigeeEnv(environment)
return apiclient.SetApigeeOrg(org)
Expand All @@ -38,21 +38,23 @@ var SetCustCmd = &cobra.Command{
if result == "" {
return fmt.Errorf("custom role must be of the format projects/{project-id}/roles/{role-name}")
}
err = environments.SetIAM(serviceAccountName, role)
err = environments.SetIAM(memberName, role, memberType)
if err != nil {
return err
}
fmt.Printf("Service account %s, granted access to %s\n", serviceAccountName, role)
fmt.Printf("Member %s, granted access to %s\n", memberName, role)
return nil
},
}

func init() {

SetCustCmd.Flags().StringVarP(&serviceAccountName, "name", "n",
"", "Service Account Name")
SetCustCmd.Flags().StringVarP(&memberName, "name", "n",
"", "Member Name, example Service Account Name")
SetCustCmd.Flags().StringVarP(&role, "role", "r",
"", "Custom IAM role in the format projects/{project-id}/roles/{role}")
SetCustCmd.Flags().StringVarP(&memberType, "memberType", "m",
"serviceAccount", "memberType must be serviceAccount, user or group")

_ = SetCustCmd.MarkFlagRequired("name")
_ = SetCustCmd.MarkFlagRequired("role")
Expand Down
14 changes: 8 additions & 6 deletions cmd/env/setdeploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,28 @@ import (
//Cmd to manage tracing of apis
var SetDepCmd = &cobra.Command{
Use: "setdeploy",
Short: "Set Apigee Deployer role for a SA on an environment",
Long: "Set Apigee Deployer role for a SA on an environment",
Short: "Set Apigee Deployer role for a member on an environment",
Long: "Set Apigee Deployer role for a member on an environment",
Args: func(cmd *cobra.Command, args []string) (err error) {
apiclient.SetApigeeEnv(environment)
return apiclient.SetApigeeOrg(org)
},
RunE: func(cmd *cobra.Command, args []string) (err error) {
err = environments.SetIAM(serviceAccountName, "deploy")
err = environments.SetIAM(memberName, "deploy", memberType)
if err != nil {
return err
}
fmt.Printf("Service account %s granted access to Apigee Deployer role\n", serviceAccountName)
fmt.Printf("Member %s granted access to Apigee Deployer role\n", memberName)
return nil
},
}

func init() {

SetDepCmd.Flags().StringVarP(&serviceAccountName, "name", "n",
"", "Service Account Name")
SetDepCmd.Flags().StringVarP(&memberName, "name", "n",
"", "Member Name, example Service Account Name")
SetDepCmd.Flags().StringVarP(&memberType, "memberType", "m",
"serviceAccount", "memberType must be serviceAccount, user or group")

_ = SetDepCmd.MarkFlagRequired("name")
}
14 changes: 8 additions & 6 deletions cmd/env/setsync.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,28 @@ import (
//Cmd to manage tracing of apis
var SetSyncCmd = &cobra.Command{
Use: "setsync",
Short: "Set Synchronization Manager role for a SA on an environment",
Long: "Set Synchronization Manager role for a SA on an environment",
Short: "Set Synchronization Manager role for a member on an environment",
Long: "Set Synchronization Manager role for a member on an environment",
Args: func(cmd *cobra.Command, args []string) (err error) {
apiclient.SetApigeeEnv(environment)
return apiclient.SetApigeeOrg(org)
},
RunE: func(cmd *cobra.Command, args []string) (err error) {
err = environments.SetIAM(serviceAccountName, "sync")
err = environments.SetIAM(memberName, "sync", memberType)
if err != nil {
return err
}
fmt.Printf("Service account %s granted access to Apigee Synchronizer Manager role\n", serviceAccountName)
fmt.Printf("Member %s granted access to Apigee Synchronizer Manager role\n", memberName)
return nil
},
}

func init() {

SetSyncCmd.Flags().StringVarP(&serviceAccountName, "name", "n",
"", "Service Account Name")
SetSyncCmd.Flags().StringVarP(&memberName, "name", "n",
"", "Member Name, example Service Account Name")
SetSyncCmd.Flags().StringVarP(&memberType, "memberType", "m",
"serviceAccount", "memberType must be serviceAccount, user or group")

_ = SetSyncCmd.MarkFlagRequired("name")
}

0 comments on commit 4e590fe

Please sign in to comment.