Skip to content

Commit bd9c7b8

Browse files
committed
fix: add organization token
1 parent 3f7d52a commit bd9c7b8

File tree

9 files changed

+463
-4
lines changed

9 files changed

+463
-4
lines changed

cloudql/github/plugin.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ func Plugin(ctx context.Context) *plugin.Plugin {
6666
"github_artifact_ai_model": tableGitHubArtifactAIModel(),
6767
"github_organization_role": tableGitHubOrganizationRole(),
6868
"github_organization_app": tableGitHubOrganizationApp(),
69+
"github_organization_token": tableGitHubOrganizationToken(),
6970
},
7071
}
7172
for key, table := range p.TableMap {
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package github
2+
3+
import (
4+
opengovernance "github.com/opengovern/og-describer-github/discovery/pkg/es"
5+
6+
"github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto"
7+
"github.com/turbot/steampipe-plugin-sdk/v5/plugin"
8+
"github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform"
9+
)
10+
11+
func gitHubOrganizationTokenColumns() []*plugin.Column {
12+
tableCols := []*plugin.Column{
13+
{
14+
Name: "authorized_credential_id",
15+
Type: proto.ColumnType_INT,
16+
Description: "The organization the member is associated with.",
17+
Transform: transform.FromField("Description.AuthorizedCredentialId")},
18+
{
19+
Name: "authorized_credential_title",
20+
Type: proto.ColumnType_STRING,
21+
Description: "The role this user has in the organization. Returns null if information is not available to viewer.",
22+
Transform: transform.FromField("Description.AuthorizedCredentialTitle")},
23+
{
24+
Name: "authorized_credential_note",
25+
Type: proto.ColumnType_STRING,
26+
Transform: transform.FromField("Description.AuthorizedCredentialNote")},
27+
{
28+
Name: "authorized_credential_expires_at",
29+
Type: proto.ColumnType_TIMESTAMP,
30+
Description: "permissions",
31+
Transform: transform.FromField("Description.AuthorizedCredentialExpiresAt")},
32+
{
33+
Name: "login",
34+
Type: proto.ColumnType_STRING,
35+
Description: "login",
36+
Transform: transform.FromField("Description.Login")},
37+
{
38+
Name: "scopes",
39+
Description: "permissions",
40+
Type: proto.ColumnType_JSON,
41+
Transform: transform.FromField("Description.Scopes")},
42+
{
43+
Name: "credential_id",
44+
Type: proto.ColumnType_INT,
45+
Description: "permissions",
46+
Transform: transform.FromField("Description.CredentialId")},
47+
{
48+
Name: "credential_type",
49+
Type: proto.ColumnType_STRING,
50+
Description: "permissions",
51+
Transform: transform.FromField("Description.CredentialType")},
52+
{
53+
Name: "credential_accessed_at",
54+
Type: proto.ColumnType_TIMESTAMP,
55+
Description: "permissions",
56+
Transform: transform.FromField("Description.CredentialAccessedAt")},
57+
{
58+
Name: "credential_authorized_at",
59+
Type: proto.ColumnType_TIMESTAMP,
60+
Description: "permissions",
61+
Transform: transform.FromField("Description.CredentialAuthorizedAt")},
62+
{
63+
Name: "token_last_eight",
64+
Type: proto.ColumnType_STRING,
65+
Description: "permissions",
66+
Transform: transform.FromField("Description.TokenLastEight")},
67+
{
68+
Name: "fingerprint",
69+
Type: proto.ColumnType_STRING,
70+
Description: "permissions",
71+
Transform: transform.FromField("Description.Fingerprint")},
72+
}
73+
74+
return tableCols
75+
}
76+
77+
func tableGitHubOrganizationToken() *plugin.Table {
78+
return &plugin.Table{
79+
Name: "github_organization_token",
80+
Description: "GitHub tokens for a given organization. GitHub Users are user accounts in GitHub.",
81+
List: &plugin.ListConfig{
82+
Hydrate: opengovernance.ListOrganizationToken,
83+
},
84+
Columns: commonColumns(gitHubOrganizationTokenColumns()),
85+
}
86+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package describers
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"github.com/opengovern/og-describer-github/discovery/pkg/models"
8+
model "github.com/opengovern/og-describer-github/discovery/provider"
9+
resilientbridge "github.com/opengovern/resilient-bridge"
10+
"github.com/opengovern/resilient-bridge/adapters"
11+
"strconv"
12+
"time"
13+
)
14+
15+
func ListOrganizationTokens(ctx context.Context,
16+
githubClient model.GitHubClient,
17+
organizationName string,
18+
stream *models.StreamSender) ([]models.Resource, error) {
19+
sdk := resilientbridge.NewResilientBridge()
20+
sdk.RegisterProvider("github", adapters.NewGitHubAdapter(githubClient.Token), &resilientbridge.ProviderConfig{
21+
UseProviderLimits: true,
22+
MaxRetries: 3,
23+
BaseBackoff: 0,
24+
})
25+
26+
var values []models.Resource
27+
28+
endpoint := fmt.Sprintf("/orgs/%s/credential-authorizations", organizationName)
29+
req := &resilientbridge.NormalizedRequest{
30+
Method: "GET",
31+
Endpoint: endpoint,
32+
Headers: map[string]string{"Accept": "application/vnd.github+json"},
33+
}
34+
35+
resp, err := sdk.Request("github", req)
36+
if err != nil {
37+
return nil, fmt.Errorf("error fetching repos: %w", err)
38+
}
39+
if resp.StatusCode != 200 {
40+
return nil, fmt.Errorf("HTTP error %d: %s", resp.StatusCode, string(resp.Data))
41+
}
42+
43+
// Decode into a slice of generic maps. We'll only parse name, archived, disabled, etc.
44+
var tokensResponse []OrganizationToken
45+
if err := json.Unmarshal(resp.Data, &tokensResponse); err != nil {
46+
return nil, fmt.Errorf("error decoding repos list: %w", err)
47+
}
48+
49+
fmt.Println(tokensResponse)
50+
51+
for _, r := range tokensResponse {
52+
value := models.Resource{
53+
ID: strconv.Itoa(int(r.AuthorizedCredentialId)),
54+
Name: r.AuthorizedCredentialTitle,
55+
Description: model.OrganizationTokenDescription{
56+
AuthorizedCredentialId: r.AuthorizedCredentialId,
57+
AuthorizedCredentialTitle: r.AuthorizedCredentialTitle,
58+
AuthorizedCredentialNote: r.AuthorizedCredentialNote,
59+
AuthorizedCredentialExpiresAt: r.AuthorizedCredentialExpiresAt,
60+
Login: r.Login,
61+
Scopes: r.Scopes,
62+
CredentialId: r.CredentialId,
63+
CredentialType: r.CredentialType,
64+
CredentialAccessedAt: r.CredentialAccessedAt,
65+
CredentialAuthorizedAt: r.CredentialAuthorizedAt,
66+
TokenLastEight: r.TokenLastEight,
67+
Fingerprint: r.Fingerprint,
68+
},
69+
}
70+
if stream != nil {
71+
if err := (*stream)(value); err != nil {
72+
return nil, err
73+
}
74+
} else {
75+
values = append(values, value)
76+
}
77+
}
78+
79+
return values, nil
80+
}
81+
82+
type OrganizationToken struct {
83+
AuthorizedCredentialId int64 `json:"authorized_credential_id"`
84+
AuthorizedCredentialTitle string `json:"authorized_credential_title"`
85+
AuthorizedCredentialNote string `json:"authorized_credential_note"`
86+
AuthorizedCredentialExpiresAt time.Time `json:"authorized_credential_expires_at"`
87+
Login string `json:"login"`
88+
Scopes []string `json:"scopes"`
89+
CredentialId int64 `json:"credential_id"`
90+
CredentialType string `json:"credential_type"`
91+
CredentialAccessedAt time.Time `json:"credential_accessed_at"`
92+
CredentialAuthorizedAt time.Time `json:"credential_authorized_at"`
93+
TokenLastEight string `json:"token_last_eight"` // Change from time.Time to string
94+
Fingerprint string `json:"fingerprint"`
95+
}

0 commit comments

Comments
 (0)