github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/cmd/roachprod/vm/azure/auth.go (about)

     1  // Copyright 2019 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package azure
    12  
    13  import (
    14  	"net/http"
    15  
    16  	"github.com/Azure/go-autorest/autorest"
    17  	"github.com/Azure/go-autorest/autorest/azure/auth"
    18  	"github.com/cockroachdb/errors"
    19  )
    20  
    21  // getAuthorizer returns an Authorizer, which uses the Azure CLI
    22  // to log into the portal.
    23  //
    24  // It would be possible to implement an OAuth2 flow, avoiding the need
    25  // to install the Azure CLI.
    26  //
    27  // The Authorizer is memoized in the Provider.
    28  func (p *Provider) getAuthorizer() (ret autorest.Authorizer, err error) {
    29  	p.mu.Lock()
    30  	ret = p.mu.authorizer
    31  	p.mu.Unlock()
    32  	if ret != nil {
    33  		return
    34  	}
    35  
    36  	// Use the azure CLI to bootstrap our authentication.
    37  	// https://docs.microsoft.com/en-us/go/azure/azure-sdk-go-authorization
    38  	ret, err = auth.NewAuthorizerFromCLI()
    39  	if err == nil {
    40  		p.mu.Lock()
    41  		p.mu.authorizer = ret
    42  		p.mu.Unlock()
    43  	} else {
    44  		err = errors.Wrap(err, "could got get Azure auth token")
    45  	}
    46  	return
    47  }
    48  
    49  // getAuthToken extracts the JWT token from the active Authorizer.
    50  func (p *Provider) getAuthToken() (string, error) {
    51  	auth, err := p.getAuthorizer()
    52  	if err != nil {
    53  		return "", err
    54  	}
    55  
    56  	// We'll steal the auth Bearer token by creating a fake HTTP request.
    57  	fake := &http.Request{}
    58  	if _, err := auth.WithAuthorization()(&stealAuth{}).Prepare(fake); err != nil {
    59  		return "", err
    60  	}
    61  	return fake.Header.Get("Authorization")[7:], nil
    62  }
    63  
    64  type stealAuth struct {
    65  }
    66  
    67  var _ autorest.Preparer = &stealAuth{}
    68  
    69  // Prepare implements the autorest.Preparer interface.
    70  func (*stealAuth) Prepare(r *http.Request) (*http.Request, error) {
    71  	return r, nil
    72  }