Skip to content

Commit

Permalink
Get extra emails when using SAML (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
loganintech authored Mar 1, 2024
1 parent 2c6e55c commit 7c1e327
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 13 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,14 @@ Flags:
Use "baton-github [command] --help" for more information about a command.
```

# Authentication

To use this Baton connector, you need to create a GitHub organization access token with the following permissions:

Org:
- Member Read and Write

Repo:
- Administrator: Read and Write
- This permission implies Metadata: Read
3 changes: 3 additions & 0 deletions pkg/connector/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ type listUsersQuery struct {
Node struct {
SamlIdentity struct {
NameId string
Emails []struct {
Value string
}
}
User struct {
Login string
Expand Down
2 changes: 1 addition & 1 deletion pkg/connector/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func (o *orgResourceType) Grants(
continue
}

ur, err := userResource(ctx, user, user.GetEmail())
ur, err := userResource(ctx, user, user.GetEmail(), nil)
if err != nil {
return nil, "", nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/connector/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func (o *repositoryResourceType) Grants(
continue
}

ur, err := userResource(ctx, user, user.GetEmail())
ur, err := userResource(ctx, user, user.GetEmail(), nil)
if err != nil {
return nil, "", nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/connector/team.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ func (o *teamResourceType) Grants(ctx context.Context, resource *v2.Resource, pT
return nil, "", nil, fmt.Errorf("github-connectorv2: failed to get team membership for user: %w", err)
}

ur, err := userResource(ctx, user, user.GetEmail())
ur, err := userResource(ctx, user, user.GetEmail(), nil)
if err != nil {
return nil, "", nil, err
}
Expand Down
51 changes: 41 additions & 10 deletions pkg/connector/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package connector
import (
"context"
"fmt"
"net/mail"
"strconv"
"strings"

Expand All @@ -16,7 +17,7 @@ import (
)

// Create a new connector resource for a github user.
func userResource(ctx context.Context, user *github.User, userEmail string) (*v2.Resource, error) {
func userResource(ctx context.Context, user *github.User, userEmail string, extraEmails []string) (*v2.Resource, error) {
displayName := user.GetName()
if displayName == "" {
// users do not always specify a name and we only get public email from
Expand All @@ -41,15 +42,21 @@ func userResource(ctx context.Context, user *github.User, userEmail string) (*v2
"user_id": strconv.Itoa(int(user.GetID())),
}

userTrait := []resource.UserTraitOption{
resource.WithEmail(userEmail, true),
resource.WithUserProfile(profile),
resource.WithStatus(v2.UserTrait_Status_STATUS_ENABLED),
}

for _, email := range extraEmails {
userTrait = append(userTrait, resource.WithEmail(email, false))
}

ret, err := resource.NewUserResource(
displayName,
resourceTypeUser,
user.GetID(),
[]resource.UserTraitOption{
resource.WithEmail(userEmail, true),
resource.WithUserProfile(profile),
resource.WithStatus(v2.UserTrait_Status_STATUS_ENABLED),
},
userTrait,
resource.WithAnnotation(
&v2.ExternalLink{Url: user.GetHTMLURL()},
&v2.V1Identifier{Id: strconv.FormatInt(user.GetID(), 10)},
Expand Down Expand Up @@ -94,7 +101,6 @@ func (o *userResourceType) List(ctx context.Context, parentID *v2.ResourceId, pt
if err != nil {
return nil, "", nil, err
}
q := listUsersQuery{}
var restApiRateLimit *v2.RateLimitDescription

opts := github.ListMembersOptions{
Expand All @@ -121,15 +127,16 @@ func (o *userResourceType) List(ctx context.Context, parentID *v2.ResourceId, pt
return nil, "", nil, err
}

q := listUsersQuery{}
rv := make([]*v2.Resource, 0, len(users))
for _, user := range users {
u, _, err := o.client.Users.GetByID(ctx, user.GetID())
if err != nil {
return nil, "", nil, err
}
userEmail := u.GetEmail()
var extraEmails []string
if hasSamlBool {
q = listUsersQuery{}
variables := map[string]interface{}{
"orgLoginName": githubv4.String(orgName),
"userName": githubv4.String(u.GetLogin()),
Expand All @@ -139,10 +146,29 @@ func (o *userResourceType) List(ctx context.Context, parentID *v2.ResourceId, pt
return nil, "", nil, err
}
if len(q.Organization.SamlIdentityProvider.ExternalIdentities.Edges) == 1 {
userEmail = q.Organization.SamlIdentityProvider.ExternalIdentities.Edges[0].Node.SamlIdentity.NameId
samlIdent := q.Organization.SamlIdentityProvider.ExternalIdentities.Edges[0].Node.SamlIdentity
userEmail = samlIdent.NameId
setUserEmail := false

if userEmail != "" {
setUserEmail = true
}
for _, email := range samlIdent.Emails {
ok := isEmail(email.Value)
if !ok {
continue
}

if !setUserEmail {
userEmail = email.Value
setUserEmail = true
} else {
extraEmails = append(extraEmails, email.Value)
}
}
}
}
ur, err := userResource(ctx, u, userEmail)
ur, err := userResource(ctx, u, userEmail, extraEmails)
if err != nil {
return nil, "", nil, err
}
Expand All @@ -162,6 +188,11 @@ func (o *userResourceType) List(ctx context.Context, parentID *v2.ResourceId, pt
return rv, pageToken, annotations, nil
}

func isEmail(email string) bool {
_, err := mail.ParseAddress(email)
return err == nil
}

func (o *userResourceType) Entitlements(_ context.Context, _ *v2.Resource, _ *pagination.Token) ([]*v2.Entitlement, string, annotations.Annotations, error) {
return nil, "", nil, nil
}
Expand Down

0 comments on commit 7c1e327

Please sign in to comment.