github.com/grailbio/base@v0.0.11/cmd/ticket-server/service.go (about)

     1  // Copyright 2018 GRAIL, Inc. All rights reserved.
     2  // Use of this source code is governed by the Apache-2.0
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  
    11  	"github.com/aws/aws-sdk-go/aws/session"
    12  	"github.com/grailbio/base/common/log"
    13  	"github.com/grailbio/base/security/ticket"
    14  	"v.io/v23/context"
    15  	"v.io/v23/rpc"
    16  	"v.io/v23/security/access"
    17  )
    18  
    19  type service struct {
    20  	name       string
    21  	kind       string
    22  	ticket     ticket.Ticket
    23  	perms      access.Permissions
    24  	awsSession *session.Session
    25  	controls   map[ticket.Control]bool
    26  }
    27  
    28  func (s *service) log(ctx *context.T, call rpc.ServerCall, parameters []ticket.Parameter, args map[string]string) {
    29  	logArgs := make([]interface{}, len(parameters)+len(args)*2+2)
    30  	i := 0
    31  	for _, p := range parameters {
    32  		logArgs[i] = p.Key
    33  		logArgs[i+1] = p.Value
    34  		i += 2
    35  	}
    36  	for k, v := range args {
    37  		logArgs[i] = k
    38  		logArgs[i+1] = v
    39  		i += 2
    40  	}
    41  	log.Info(ctx, "Fetching ticket.", logArgs...)
    42  }
    43  
    44  func (s *service) get(ctx *context.T, call rpc.ServerCall, parameters []ticket.Parameter, args map[string]string) (ticket.Ticket, error) {
    45  	s.log(ctx, call, parameters, args)
    46  	if ok, err := s.checkControls(ctx, call, args); !ok {
    47  		return nil, err
    48  	}
    49  	remoteBlessings := call.Security().RemoteBlessings()
    50  	ticketCtx := ticket.NewTicketContext(ctx, s.awsSession, remoteBlessings)
    51  	switch t := s.ticket.(type) {
    52  	case ticket.TicketAwsTicket:
    53  		return t.Build(ticketCtx, parameters)
    54  	case ticket.TicketS3Ticket:
    55  		return t.Build(ticketCtx, parameters)
    56  	case ticket.TicketSshCertificateTicket:
    57  		return t.Build(ticketCtx, parameters)
    58  	case ticket.TicketEcrTicket:
    59  		return t.Build(ticketCtx, parameters)
    60  	case ticket.TicketTlsServerTicket:
    61  		return t.Build(ticketCtx, parameters)
    62  	case ticket.TicketTlsClientTicket:
    63  		return t.Build(ticketCtx, parameters)
    64  	case ticket.TicketDockerTicket:
    65  		return t.Build(ticketCtx, parameters)
    66  	case ticket.TicketDockerServerTicket:
    67  		return t.Build(ticketCtx, parameters)
    68  	case ticket.TicketDockerClientTicket:
    69  		return t.Build(ticketCtx, parameters)
    70  	case ticket.TicketB2Ticket:
    71  		return t.Build(ticketCtx, parameters)
    72  	case ticket.TicketVanadiumTicket:
    73  		return t.Build(ticketCtx, parameters)
    74  	case ticket.TicketGenericTicket:
    75  		return t.Build(ticketCtx, parameters)
    76  	}
    77  	return nil, fmt.Errorf("not implemented")
    78  }
    79  
    80  func (s *service) Get(ctx *context.T, call rpc.ServerCall) (ticket.Ticket, error) {
    81  	log.Info(ctx, "get request", "blessing", call.Security().RemoteBlessings(), "ticket", call.Suffix())
    82  	return s.get(ctx, call, nil, nil)
    83  }
    84  
    85  func (s *service) GetWithArgs(ctx *context.T, call rpc.ServerCall, args map[string]string) (ticket.Ticket, error) {
    86  	return s.get(ctx, call, nil, args)
    87  }
    88  
    89  func (s *service) GetWithParameters(ctx *context.T, call rpc.ServerCall, parameters []ticket.Parameter) (ticket.Ticket, error) {
    90  	return s.get(ctx, call, parameters, nil)
    91  }
    92  
    93  // GetPermissions implements the Object interface from
    94  // v.io/v23/services/permissions.
    95  func (s *service) GetPermissions(ctx *context.T, call rpc.ServerCall) (perms access.Permissions, version string, _ error) {
    96  	// We don't compose a proper version string because we don't allow setting the
    97  	// permissions.
    98  	return s.perms, "", nil
    99  }
   100  
   101  // GetPermissions implements the Object interface from
   102  // v.io/v23/services/permissions.
   103  func (s *service) SetPermissions(ctx *context.T, call rpc.ServerCall, perms access.Permissions, version string) error {
   104  	return fmt.Errorf("not implemented")
   105  }
   106  
   107  func (s *service) checkControls(_ *context.T, _ rpc.ServerCall, args map[string]string) (bool, error) {
   108  	for control, required := range s.controls {
   109  		if required && args[control.String()] == "" {
   110  			return false, errors.New("missing required argument: " + control.String())
   111  		}
   112  	}
   113  	return true, nil
   114  }