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 }