github.com/nais/knorten@v0.0.0-20240104110906-55926958e361/pkg/gcp/iam.go (about)

     1  package gcp
     2  
     3  import (
     4  	"context"
     5  
     6  	"cloud.google.com/go/iam"
     7  	secretmanager "cloud.google.com/go/secretmanager/apiv1"
     8  	"github.com/googleapis/gax-go/v2/apierror"
     9  	"google.golang.org/grpc/codes"
    10  	"k8s.io/utils/strings/slices"
    11  )
    12  
    13  const secretRoleName = "roles/owner"
    14  
    15  func SetUsersSecretOwnerBinding(ctx context.Context, users []string, secret string) error {
    16  	users = addUserTypePrefix(users)
    17  
    18  	client, err := secretmanager.NewClient(ctx)
    19  	if err != nil {
    20  		return err
    21  	}
    22  	defer client.Close()
    23  
    24  	handle := client.IAM(secret)
    25  	policy, err := handle.Policy(ctx)
    26  	if err != nil {
    27  		return err
    28  	}
    29  
    30  	policyMembers := policy.Members(secretRoleName)
    31  	for _, member := range policyMembers {
    32  		if !slices.Contains(users, member) {
    33  			policy.Remove(member, secretRoleName)
    34  		}
    35  	}
    36  
    37  	err = handle.SetPolicy(ctx, policy)
    38  	if err != nil {
    39  		return err
    40  	}
    41  
    42  	for _, user := range users {
    43  		if err := updatePolicy(ctx, handle, user); err != nil {
    44  			return err
    45  		}
    46  	}
    47  
    48  	return nil
    49  }
    50  
    51  func updatePolicy(ctx context.Context, handle *iam.Handle, user string) error {
    52  	policy, err := handle.Policy(ctx)
    53  	if err != nil {
    54  		return err
    55  	}
    56  
    57  	policyMembers := policy.Members(secretRoleName)
    58  	if !slices.Contains(policyMembers, user) {
    59  		policy.Add(user, secretRoleName)
    60  		err = handle.SetPolicy(ctx, policy)
    61  		if err != nil {
    62  			apiError, ok := apierror.FromError(err)
    63  			if ok && apiError.GRPCStatus().Code() == codes.InvalidArgument {
    64  				return nil
    65  			}
    66  
    67  			return err
    68  		}
    69  	}
    70  
    71  	return nil
    72  }
    73  
    74  func addUserTypePrefix(users []string) []string {
    75  	prefixedUsers := make([]string, len(users))
    76  	for i, u := range users {
    77  		prefixedUsers[i] = "user:" + u
    78  	}
    79  
    80  	return prefixedUsers
    81  }