github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/pkg/remoteenforcer/internal/tokenissuer/tokenissuer.go (about)

     1  package tokenissuer
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"os"
     8  	"reflect"
     9  	"time"
    10  
    11  	"go.aporeto.io/enforcerd/trireme-lib/common"
    12  	"go.aporeto.io/enforcerd/trireme-lib/controller/constants"
    13  	"go.aporeto.io/enforcerd/trireme-lib/controller/internal/enforcer/utils/rpcwrapper"
    14  	"go.uber.org/zap"
    15  )
    16  
    17  // TokenClient interface provides a start function. the client is used to
    18  // request tokens.
    19  type TokenClient interface {
    20  	Run(ctx context.Context) error
    21  	Issue(ctx context.Context, contextID string, stype common.ServiceTokenType, audience string, validity time.Duration) (string, error)
    22  }
    23  
    24  const (
    25  	tokenIssuerContextID = "UNUSED"
    26  	retrieveTokenCommand = "ProxyRPCServer.RetrieveToken"
    27  )
    28  
    29  // Client represents the remote API client.
    30  type Client struct {
    31  	rpchdl     rpcwrapper.RPCClient
    32  	secret     string
    33  	socketPath string
    34  	stop       chan bool
    35  }
    36  
    37  // NewClient returns a remote API client that can be used for
    38  // issuing API calls to the master enforcer.
    39  func NewClient() (*Client, error) {
    40  	c := &Client{
    41  		rpchdl:     rpcwrapper.NewRPCWrapper(),
    42  		secret:     os.Getenv(constants.EnvStatsSecret),
    43  		socketPath: os.Getenv(constants.EnvStatsChannel),
    44  		stop:       make(chan bool),
    45  	}
    46  	if c.socketPath == "" {
    47  		return nil, errors.New("no path to socket provided")
    48  	}
    49  	if c.secret == "" {
    50  		return nil, errors.New("no secret provided for  channel")
    51  	}
    52  
    53  	return c, nil
    54  }
    55  
    56  // RetrieveToken will issue a token request to the main over the RPC channnel.
    57  func (c *Client) RetrieveToken(contextID string, stype common.ServiceTokenType, audience string, validity time.Duration) (string, error) {
    58  
    59  	request := &rpcwrapper.Request{
    60  		Payload: &rpcwrapper.TokenRequestPayload{
    61  			ContextID:        contextID,
    62  			Audience:         audience,
    63  			Validity:         validity,
    64  			ServiceTokenType: stype,
    65  		},
    66  	}
    67  
    68  	response := &rpcwrapper.Response{}
    69  
    70  	if err := c.rpchdl.RemoteCall(tokenIssuerContextID, retrieveTokenCommand, request, response); err != nil {
    71  		return "", err
    72  	}
    73  
    74  	payload, ok := response.Payload.(rpcwrapper.TokenResponsePayload)
    75  	if !ok {
    76  		return "", fmt.Errorf("unrecognized response payload. Received payload is %s", reflect.TypeOf(response.Payload))
    77  	}
    78  
    79  	return payload.Token, nil
    80  }
    81  
    82  // Issue implements the ServiceTokenIssuer interface.
    83  func (c *Client) Issue(ctx context.Context, contextID string, stype common.ServiceTokenType, audience string, validity time.Duration) (string, error) {
    84  	return c.RetrieveToken(contextID, stype, audience, validity)
    85  }
    86  
    87  // Run will initialize the client.
    88  func (c *Client) Run(ctx context.Context) error {
    89  	if err := c.rpchdl.NewRPCClient(tokenIssuerContextID, c.socketPath, c.secret); err != nil {
    90  		zap.L().Error("CounterClient RPC client cannot connect", zap.Error(err))
    91  		return err
    92  	}
    93  	return nil
    94  }