k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/gencred/pkg/secretmanager/secretmanager.go (about)

     1  /*
     2  Copyright 2021 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package secretmanager
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	secretmanager "cloud.google.com/go/secretmanager/apiv1"
    24  	"cloud.google.com/go/secretmanager/apiv1/secretmanagerpb"
    25  	"google.golang.org/api/iterator"
    26  )
    27  
    28  // Client is a wrapper of secretmanager client
    29  type Client struct {
    30  	// ProjectID is GCP project in which to store secrets in Secret Manager.
    31  	ProjectID string
    32  	client    *secretmanager.Client
    33  	dryrun    bool
    34  }
    35  
    36  // ClientInterface is the interface for manipulating secretmanager
    37  type ClientInterface interface {
    38  	CreateSecret(ctx context.Context, secretID string) (*secretmanagerpb.Secret, error)
    39  	AddSecretVersion(ctx context.Context, secretName string, payload []byte) error
    40  	ListSecrets(ctx context.Context) ([]*secretmanagerpb.Secret, error)
    41  }
    42  
    43  // NewClient creates a client for secretmanager, it would fail if not authenticated
    44  func NewClient(projectID string, dryrun bool) (*Client, error) {
    45  	// Create the client.
    46  	ctx := context.Background()
    47  	client, err := secretmanager.NewClient(ctx)
    48  	if err != nil {
    49  		return nil, fmt.Errorf("failed to setup client: %w", err)
    50  	}
    51  	return &Client{ProjectID: projectID, client: client, dryrun: dryrun}, nil
    52  }
    53  
    54  // CreateSecret creates a secret
    55  func (c *Client) CreateSecret(ctx context.Context, secretID string) (*secretmanagerpb.Secret, error) {
    56  	if c.dryrun {
    57  		return nil, nil
    58  	}
    59  	// Create the request to create the secret.
    60  	createSecretReq := &secretmanagerpb.CreateSecretRequest{
    61  		Parent:   fmt.Sprintf("projects/%s", c.ProjectID),
    62  		SecretId: secretID,
    63  		Secret: &secretmanagerpb.Secret{
    64  			Replication: &secretmanagerpb.Replication{
    65  				Replication: &secretmanagerpb.Replication_Automatic_{
    66  					Automatic: &secretmanagerpb.Replication_Automatic{},
    67  				},
    68  			},
    69  		},
    70  	}
    71  
    72  	return c.client.CreateSecret(ctx, createSecretReq)
    73  }
    74  
    75  // AddSecretVersion adds a secret version, aka update the value of a secret
    76  func (c *Client) AddSecretVersion(ctx context.Context, secretName string, payload []byte) error {
    77  	if c.dryrun {
    78  		return nil
    79  	}
    80  	// Build the request.
    81  	addSecretVersionReq := &secretmanagerpb.AddSecretVersionRequest{
    82  		Parent: fmt.Sprintf("projects/%s/secrets/%s", c.ProjectID, secretName),
    83  		Payload: &secretmanagerpb.SecretPayload{
    84  			Data: payload,
    85  		},
    86  	}
    87  
    88  	// Call the API.
    89  	_, err := c.client.AddSecretVersion(ctx, addSecretVersionReq)
    90  	return err
    91  }
    92  
    93  // ListSecrets lists all secrets under current project
    94  func (c *Client) ListSecrets(ctx context.Context) ([]*secretmanagerpb.Secret, error) {
    95  	var res []*secretmanagerpb.Secret
    96  	// Build the request.
    97  	listRequest := &secretmanagerpb.ListSecretsRequest{
    98  		Parent: fmt.Sprintf("projects/%s", c.ProjectID),
    99  	}
   100  
   101  	// Call the API.
   102  	it := c.client.ListSecrets(ctx, listRequest)
   103  	for {
   104  		s, err := it.Next()
   105  		if err != nil {
   106  			if err == iterator.Done {
   107  				break
   108  			}
   109  			return nil, err
   110  		}
   111  		res = append(res, s)
   112  	}
   113  	return res, nil
   114  }