-
Notifications
You must be signed in to change notification settings - Fork 775
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: expose SAML external identity exposed for GitHub user (#1796)
* create github_user_external_identity datasource * add scim information and error handling for bad username org combo * cleanup commentzs * add docs for external identity * move external identity to its own struct * add variable to make referencing external identity easier * add test * add documentation * remove old docs * add docs reference in github.erb --------- Co-authored-by: Keegan Campbell <[email protected]>
- Loading branch information
1 parent
0fb2e1d
commit 77cfacb
Showing
6 changed files
with
223 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
package github | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
"github.com/shurcooL/githubv4" | ||
) | ||
|
||
func dataSourceGithubUserExternalIdentity() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: dataSourceGithubUserExternalIdentityRead, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"username": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
"saml_identity": { | ||
Type: schema.TypeMap, | ||
Computed: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
}, | ||
}, | ||
"scim_identity": { | ||
Type: schema.TypeMap, | ||
Computed: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
}, | ||
}, | ||
"login": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func dataSourceGithubUserExternalIdentityRead(d *schema.ResourceData, meta interface{}) error { | ||
username := d.Get("username").(string) | ||
|
||
client := meta.(*Owner).v4client | ||
orgName := meta.(*Owner).name | ||
|
||
var query struct { | ||
Organization struct { | ||
SamlIdentityProvider struct { | ||
ExternalIdentities `graphql:"externalIdentities(first: 1, login:$username)"` // There should only ever be one external identity configured | ||
} | ||
} `graphql:"organization(login: $orgName)"` | ||
} | ||
|
||
variables := map[string]interface{}{ | ||
"orgName": githubv4.String(orgName), | ||
"username": githubv4.String(username), | ||
} | ||
|
||
err := client.Query(meta.(*Owner).StopContext, &query, variables) | ||
if err != nil { | ||
return err | ||
} | ||
if len(query.Organization.SamlIdentityProvider.ExternalIdentities.Edges) == 0 { | ||
return fmt.Errorf("there was no external identity found for username %q in Organization %q", username, orgName) | ||
} | ||
|
||
externalIdentityNode := query.Organization.SamlIdentityProvider.ExternalIdentities.Edges[0].Node // There should only be one user in this list | ||
|
||
samlIdentity := map[string]string{ | ||
"family_name": string(externalIdentityNode.SamlIdentity.FamilyName), | ||
"given_name": string(externalIdentityNode.SamlIdentity.GivenName), | ||
"name_id": string(externalIdentityNode.SamlIdentity.NameId), | ||
"username": string(externalIdentityNode.SamlIdentity.Username), | ||
} | ||
|
||
scimIdentity := map[string]string{ | ||
"family_name": string(externalIdentityNode.ScimIdentity.FamilyName), | ||
"given_name": string(externalIdentityNode.ScimIdentity.GivenName), | ||
"username": string(externalIdentityNode.ScimIdentity.Username), | ||
} | ||
|
||
login := string(externalIdentityNode.User.Login) | ||
|
||
d.SetId(fmt.Sprintf("%s/%s", orgName, username)) | ||
d.Set("saml_identity", samlIdentity) | ||
d.Set("scim_identity", scimIdentity) | ||
d.Set("login", login) | ||
d.Set("username", login) | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package github | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
) | ||
|
||
func TestAccGithubUserExternalIdentity(t *testing.T) { | ||
if isEnterprise != "true" { | ||
t.Skip("Skipping because `ENTERPRISE_ACCOUNT` is not set or set to false") | ||
} | ||
|
||
t.Run("queries without error", func(t *testing.T) { | ||
config := ` | ||
data "github_user_external_identity" "test" { | ||
}` | ||
|
||
check := resource.ComposeAggregateTestCheckFunc( | ||
resource.TestCheckResourceAttrSet("data.github_user_external_identity.test", "login"), | ||
resource.TestCheckResourceAttrSet("data.github_user_external_identity.test", "saml_identity.name_id"), | ||
resource.TestCheckResourceAttrSet("data.github_user_external_identity.test", "scim_identity.username"), | ||
) | ||
|
||
testCase := func(t *testing.T, mode string) { | ||
resource.Test(t, resource.TestCase{ | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: config, | ||
Check: check, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
t.Run("with an anonymous account", func(t *testing.T) { | ||
t.Skip("anonymous account not supported for this operation") | ||
}) | ||
|
||
t.Run("with an individual account", func(t *testing.T) { | ||
t.Skip("individual account not supported for this operation") | ||
}) | ||
|
||
t.Run("with an user accoy", func(t *testing.T) { | ||
testCase(t, organization) | ||
}) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
--- | ||
layout: "github" | ||
page_title: "GitHub: github_user_external_identity" | ||
description: |- | ||
Get a specific organization member's SAML/SCIM linked external identity | ||
--- | ||
|
||
# github_user_external_identity | ||
|
||
Use this data source to retrieve a specific organization member's SAML or SCIM user | ||
attributes. | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
data "github_user_external_identity" "example_user" { | ||
username = "example-user" | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
- `username` - (Required) The username of the member to fetch external identity for. | ||
|
||
## Attributes Reference | ||
|
||
- `login` - The username of the GitHub user | ||
- `saml_identity` - An Object containing the user's SAML data. This object will | ||
be empty if the user is not managed by SAML. | ||
- `scim_identity` - An Object contining the user's SCIM data. This object will | ||
be empty if the user is not managed by SCIM. | ||
|
||
--- | ||
|
||
If a user is managed by SAML, the `saml_identity` object will contain: | ||
|
||
- `name_id` - The member's SAML NameID | ||
- `username` - The member's SAML Username | ||
- `family_name` - The member's SAML Family Name | ||
- `given_name` - The member's SAML Given Name | ||
|
||
--- | ||
|
||
If a user is managed by SCIM, the `scim_identity` object will contain: | ||
|
||
- `scim_username` - The member's SCIM Username. (will be empty string if user is | ||
not managed by SCIM) | ||
- `scim_family_name` - The member's SCIM Family Name | ||
- `scim_given_name` - The member's SCIM Given Name |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters