...

Source file src/github.com/sigstore/cosign/v2/pkg/providers/google/google.go

Documentation: github.com/sigstore/cosign/v2/pkg/providers/google

     1  //
     2  // Copyright 2021 The Sigstore 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  package google
    17  
    18  import (
    19  	"context"
    20  	"os"
    21  	"strings"
    22  
    23  	"google.golang.org/api/idtoken"
    24  	"google.golang.org/api/impersonate"
    25  
    26  	"github.com/sigstore/cosign/v2/pkg/cosign/env"
    27  	"github.com/sigstore/cosign/v2/pkg/providers"
    28  )
    29  
    30  func init() {
    31  	providers.Register("google-workload-identity", &googleWorkloadIdentity{})
    32  	providers.Register("google-impersonate", &googleImpersonate{})
    33  }
    34  
    35  type googleWorkloadIdentity struct{}
    36  
    37  var _ providers.Interface = (*googleWorkloadIdentity)(nil)
    38  
    39  // gceProductNameFile is the product file path that contains the cloud service name.
    40  // This is a variable instead of a const to enable testing.
    41  var gceProductNameFile = "/sys/class/dmi/id/product_name"
    42  
    43  // Enabled implements providers.Interface
    44  // This is based on k8s.io/kubernetes/pkg/credentialprovider/gcp
    45  func (gwi *googleWorkloadIdentity) Enabled(ctx context.Context) bool {
    46  	data, err := os.ReadFile(gceProductNameFile)
    47  	if err != nil {
    48  		return false
    49  	}
    50  	name := strings.TrimSpace(string(data))
    51  	if name == "Google" || name == "Google Compute Engine" {
    52  		// Just because we're on Google, does not mean workload identity is available.
    53  		// TODO(mattmoor): do something better than this.
    54  		_, err := gwi.Provide(ctx, "garbage")
    55  		return err == nil
    56  	}
    57  	return false
    58  }
    59  
    60  // Provide implements providers.Interface
    61  func (gwi *googleWorkloadIdentity) Provide(ctx context.Context, audience string) (string, error) {
    62  	ts, err := idtoken.NewTokenSource(ctx, audience)
    63  	if err != nil {
    64  		return "", err
    65  	}
    66  	tok, err := ts.Token()
    67  	if err != nil {
    68  		return "", err
    69  	}
    70  	return tok.AccessToken, nil
    71  }
    72  
    73  type googleImpersonate struct{}
    74  
    75  var _ providers.Interface = (*googleImpersonate)(nil)
    76  
    77  // Enabled implements providers.Interface
    78  func (gi *googleImpersonate) Enabled(_ context.Context) bool {
    79  	// The "impersonate" method requires a target service account to impersonate.
    80  	return env.Getenv(env.VariableGoogleServiceAccountName) != ""
    81  }
    82  
    83  // Provide implements providers.Interface
    84  func (gi *googleImpersonate) Provide(ctx context.Context, audience string) (string, error) {
    85  	target := env.Getenv(env.VariableGoogleServiceAccountName)
    86  	ts, err := impersonate.IDTokenSource(ctx, impersonate.IDTokenConfig{
    87  		Audience:        audience,
    88  		TargetPrincipal: target,
    89  		IncludeEmail:    true,
    90  	})
    91  	if err != nil {
    92  		return "", err
    93  	}
    94  	tok, err := ts.Token()
    95  	if err != nil {
    96  		return "", err
    97  	}
    98  	return tok.AccessToken, nil
    99  }
   100  

View as plain text