storj.io/uplink@v1.13.0/edge/access.go (about)

     1  // Copyright (C) 2021 Storj Labs, Inc.
     2  // See LICENSE for copying information.
     3  
     4  package edge
     5  
     6  import (
     7  	"context"
     8  	"errors"
     9  
    10  	"github.com/zeebo/errs"
    11  
    12  	"storj.io/common/pb"
    13  	"storj.io/common/rpc"
    14  	"storj.io/uplink"
    15  )
    16  
    17  // We use uplinkError.* instead of errs.* to add a prefix "uplink" to every error.
    18  // It is not called "edge" on purpose so that the entire library emits the same error prefix.
    19  var uplinkError = errs.Class("uplink")
    20  
    21  // ErrAuthDialFailed is a network or protocol error.
    22  var ErrAuthDialFailed = errors.New("dial to auth service failed")
    23  
    24  // ErrRegisterAccessFailed is an internal error in the auth service.
    25  var ErrRegisterAccessFailed = errors.New("register access for edge services failed")
    26  
    27  // Credentials give access to the multi-tenant gateway.
    28  // These work in S3 clients.
    29  type Credentials struct {
    30  	// Base32
    31  	// This is also used in the linkshare url path.
    32  	AccessKeyID string
    33  	// Base32
    34  	SecretKey string
    35  	// HTTP(S) URL to the gateway.
    36  	Endpoint string
    37  }
    38  
    39  // RegisterAccessOptions contains optional parameters for RegisterAccess.
    40  type RegisterAccessOptions struct {
    41  	// Whether objects can be read without authentication.
    42  	Public bool
    43  }
    44  
    45  // RegisterAccess gets credentials for the Storj-hosted Gateway and linkshare service.
    46  // All files accessible under the Access are then also accessible via those services.
    47  // If you call this function a lot, and the use case allows it,
    48  // please limit the lifetime of the credentials
    49  // by setting Permission.NotAfter when creating the Access.
    50  func (config *Config) RegisterAccess(
    51  	ctx context.Context,
    52  	access *uplink.Access,
    53  	options *RegisterAccessOptions,
    54  ) (*Credentials, error) {
    55  	if config.AuthServiceAddress == "" {
    56  		return nil, uplinkError.New("AuthServiceAddress is missing")
    57  	}
    58  
    59  	if options == nil {
    60  		options = &RegisterAccessOptions{}
    61  	}
    62  
    63  	var conn *rpc.Conn
    64  	var err error
    65  	if config.InsecureUnencryptedConnection || config.InsecureSkipVerify {
    66  		conn, err = config.createDialer().DialAddressUnencrypted(ctx, config.AuthServiceAddress)
    67  	} else {
    68  		conn, err = config.createDialer().DialAddressHostnameVerification(ctx, config.AuthServiceAddress)
    69  	}
    70  
    71  	if err != nil {
    72  		return nil, uplinkError.New("%w: %v", ErrAuthDialFailed, err)
    73  	}
    74  	defer func() {
    75  		_ = conn.Close()
    76  	}()
    77  
    78  	client := pb.NewDRPCEdgeAuthClient(conn)
    79  
    80  	serializedAccess, err := access.Serialize()
    81  	if err != nil {
    82  		return nil, uplinkError.Wrap(err)
    83  	}
    84  
    85  	registerGatewayResponse, err := client.RegisterAccess(ctx, &pb.EdgeRegisterAccessRequest{
    86  		AccessGrant: serializedAccess,
    87  		Public:      options.Public,
    88  	})
    89  
    90  	if err != nil {
    91  		return nil, uplinkError.New("%w: %v", ErrRegisterAccessFailed, err)
    92  	}
    93  
    94  	credentials := Credentials{
    95  		AccessKeyID: registerGatewayResponse.AccessKeyId,
    96  		SecretKey:   registerGatewayResponse.SecretKey,
    97  		Endpoint:    registerGatewayResponse.Endpoint,
    98  	}
    99  
   100  	return &credentials, nil
   101  }