github.com/hellofresh/janus@v0.0.0-20230925145208-ce8de8183c67/pkg/jwt/github/provider.go (about)

     1  package github
     2  
     3  import (
     4  	"errors"
     5  	"net/http"
     6  	"strings"
     7  	"sync"
     8  
     9  	"github.com/dgrijalva/jwt-go"
    10  	"github.com/google/go-github/github"
    11  
    12  	"github.com/hellofresh/janus/pkg/config"
    13  	"github.com/hellofresh/janus/pkg/jwt/provider"
    14  )
    15  
    16  func init() {
    17  	provider.Register("github", &Provider{})
    18  }
    19  
    20  // Provider abstracts the authentication for github
    21  type Provider struct {
    22  	provider.Verifier
    23  
    24  	teams  []Team
    25  	config config.Credentials
    26  }
    27  
    28  // Build acts like the constructor for a provider
    29  func (gp *Provider) Build(config config.Credentials) provider.Provider {
    30  	client := NewClient()
    31  	teams := gp.teamConfigsToTeam(config.Github.Teams)
    32  
    33  	return &Provider{
    34  		Verifier: provider.NewVerifierBasket(
    35  			NewTeamVerifier(teams, client),
    36  			NewOrganizationVerifier(config.Github.Organizations, client),
    37  		),
    38  		teams:  teams,
    39  		config: config,
    40  	}
    41  }
    42  
    43  // GetClaims returns a JWT Map Claim
    44  func (gp *Provider) GetClaims(httpClient *http.Client) (jwt.MapClaims, error) {
    45  	client := NewClient()
    46  
    47  	var (
    48  		wg            sync.WaitGroup
    49  		user          *github.User
    50  		usersOrgTeams OrganizationTeams
    51  		errs          []string
    52  	)
    53  
    54  	wg.Add(2)
    55  	go func() {
    56  		defer wg.Done()
    57  		var err error
    58  		user, err = client.CurrentUser(httpClient)
    59  		if err != nil {
    60  			errs = append(errs, "failed to get github users")
    61  		}
    62  	}()
    63  
    64  	go func() {
    65  		defer wg.Done()
    66  		var err error
    67  		usersOrgTeams, err = client.Teams(httpClient)
    68  		if err != nil {
    69  			errs = append(errs, "failed to get github teams")
    70  		}
    71  	}()
    72  	wg.Wait()
    73  
    74  	if len(errs) > 0 {
    75  		return nil, errors.New(strings.Join(errs, ", "))
    76  	}
    77  
    78  	return jwt.MapClaims{
    79  		"sub":      *user.Login,
    80  		"is_admin": gp.isAdmin(usersOrgTeams),
    81  	}, nil
    82  }
    83  
    84  func (gp *Provider) teamConfigsToTeam(configTeams map[string]string) []Team {
    85  	var teams []Team
    86  	for org, team := range configTeams {
    87  		teams = append(teams, Team{
    88  			Name:         team,
    89  			Organization: org,
    90  		})
    91  	}
    92  	return teams
    93  }
    94  
    95  func (gp *Provider) isAdmin(usersOrgTeams OrganizationTeams) bool {
    96  	for _, team := range gp.teams {
    97  		if teams, ok := usersOrgTeams[team.Organization]; ok {
    98  			for _, teamUserBelongsTo := range teams {
    99  				if teamUserBelongsTo == gp.config.JanusAdminTeam {
   100  					return true
   101  				}
   102  			}
   103  		}
   104  	}
   105  	return false
   106  }