...

Source file src/edge-infra.dev/pkg/edge/api/services/channels/channel_iam_service.go

Documentation: edge-infra.dev/pkg/edge/api/services/channels

     1  package channels
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"fmt"
     7  
     8  	iamAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/iam/v1beta1"
     9  	secretmanagerAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/secretmanager/v1beta1"
    10  	"sigs.k8s.io/controller-runtime/pkg/client"
    11  
    12  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/k8s/v1alpha1"
    13  	"github.com/google/uuid"
    14  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    15  
    16  	"edge-infra.dev/pkg/edge/api/graph/model"
    17  	chariotClientApi "edge-infra.dev/pkg/edge/chariot/client"
    18  	"edge-infra.dev/pkg/edge/edgeencrypt"
    19  	"edge-infra.dev/pkg/lib/gcp/iam"
    20  	"edge-infra.dev/pkg/lib/gcp/iam/roles"
    21  )
    22  
    23  const sqlCreateChannelServiceAccount = `INSERT INTO channels_service_accounts(channel_id, serviceAccountEmail)
    24  	VALUES ($1, $2)
    25  	RETURNING channel_sa_id, channel_id, serviceAccountEmail, created_at`
    26  
    27  func (cs *ChannelService) CreateChannelIAM(ctx context.Context, channelID uuid.UUID, saEmail string) (*model.ChannelIAMPolicy, error) {
    28  	tx, txErr := cs.db.BeginTx(ctx, &sql.TxOptions{})
    29  
    30  	if txErr != nil {
    31  		return nil, txErr
    32  	}
    33  
    34  	var row = cs.db.QueryRowContext(ctx, sqlCreateChannelServiceAccount,
    35  		channelID,
    36  		saEmail,
    37  	)
    38  
    39  	channelIAMPolicy, err := scanChannelServiceAccount(row)
    40  
    41  	if err != nil {
    42  		return nil, fmt.Errorf("failed to insert channel service account entry in sql: %w", err)
    43  	}
    44  
    45  	sendToChariotErr := cs.createChannelIAMPolicyBinding(ctx, channelIAMPolicy.ChannelSaID, channelIAMPolicy.SaEmail, cs.foremanProjectID)
    46  
    47  	if sendToChariotErr != nil {
    48  		if rollbackErr := tx.Rollback(); rollbackErr != nil {
    49  			return nil, rollbackErr
    50  		}
    51  	}
    52  
    53  	if txCommitErr := tx.Commit(); txCommitErr != nil {
    54  		return nil, txCommitErr
    55  	}
    56  
    57  	return &channelIAMPolicy, nil
    58  }
    59  
    60  func (cs *ChannelService) createChannelIAMPolicyBinding(ctx context.Context, channelSAID, saEmail, foremanProjectID string) error {
    61  	memberEmail := iam.SvcAccountMember(saEmail)
    62  
    63  	channelIAMPolicy := &iamAPI.IAMPolicyMember{
    64  		ObjectMeta: metav1.ObjectMeta{
    65  			Name:      fmt.Sprintf("channel-iam-%s", channelSAID),
    66  			Namespace: edgeencrypt.DecryptionName,
    67  		},
    68  		TypeMeta: metav1.TypeMeta{
    69  			APIVersion: iamAPI.IAMPolicyMemberGVK.GroupVersion().String(),
    70  			Kind:       iamAPI.IAMPolicyMemberGVK.Kind,
    71  		},
    72  		Spec: iamAPI.IAMPolicyMemberSpec{
    73  			Member: &memberEmail,
    74  			ResourceRef: v1alpha1.IAMResourceRef{
    75  				APIVersion: secretmanagerAPI.SecretManagerSecretGVK.GroupVersion().String(),
    76  				Kind:       secretmanagerAPI.SecretManagerSecretGVK.Kind,
    77  				External:   fmt.Sprintf("projects/%s/secrets/%s", foremanProjectID, edgeencrypt.DecryptionTokenSecretManager),
    78  			},
    79  			Role: roles.SecretAccessor,
    80  		},
    81  	}
    82  
    83  	sendToChariotErr := cs.sendChariotMessage(ctx, channelIAMPolicy)
    84  
    85  	if sendToChariotErr != nil {
    86  		return sendToChariotErr
    87  	}
    88  
    89  	return nil
    90  }
    91  
    92  func (cs *ChannelService) sendChariotMessage(ctx context.Context, object ...client.Object) error {
    93  	chariotMessage, err := chariotClientApi.
    94  		NewChariotMessage().
    95  		SetOperation(chariotClientApi.Create).
    96  		SetBanner(cs.foremanProjectID).
    97  		SetCluster("foreman0").
    98  		AddK8sBase64Object(object...)
    99  
   100  	if err != nil {
   101  		return err
   102  	}
   103  
   104  	if err := cs.ChariotService.InvokeChariotPubsub(ctx, chariotMessage, nil); err != nil {
   105  		return fmt.Errorf("error calling chariot v2: %w", err)
   106  	}
   107  
   108  	return nil
   109  }
   110  

View as plain text