Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,19 @@ Once the PAT is created, GitHub will present it to you as shown below. You must
2. Load `github.ps1` in your current PowerShell session:

```powershell
. ./github.ps1
. ./githound.ps1
```

3. Create a GitHub Session using your Personal Access Token.
3. Create a GitHub Session using your Personal Access Token (PAT) or through a Github App.

```powershell
#Github Session with PAT
$session = New-GitHubSession -OrganizationName <Name of your Organization> -Token (Get-Clipboard)
#Github Session with Github App, require powershell 7.0 or later
$session = New-GithubAppSession -OrganizationName <Name of your Organization> -ClientId (Get-Clipboard) -PrivateKeyPath <Path to Private Key Pem>
```

Note: You must specify the name of your GitHub organziation. For example, this repository is part of the `SpecterOps` organization, so I would specify `SpecterOps` as the argument for the OrganizationName parameter. Additionally, you must specify your Personal Access Token. I find that it is easiest to paste it directly from the clipboard as this is where it will be after you create it or if you save it in a password manager.
Note: You must specify the name of your GitHub organziation. For example, this repository is part of the `SpecterOps` organization, so I would specify `SpecterOps` as the argument for the OrganizationName parameter. Additionally, you must specify your Personal Access Token (or Priv key and Client ID). I find that it is easiest to paste it directly from the clipboard as this is where it will be after you create it or if you save it in a password manager.

4. Run the collection on the specified organization:

Expand Down
53 changes: 51 additions & 2 deletions githound.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,55 @@ function New-GithubSession {
OrganizationName = $OrganizationName
}
}
function New-GithubAppSession {
[OutputType('GitHound.Session')]
[CmdletBinding()]
Param(
[Parameter(Position=0, Mandatory = $true)]
[string]
$OrganizationName,

[Parameter(Position=1, Mandatory = $true)]
[string]
$ClientId,

[Parameter(Position=2, Mandatory = $false)]
[string]
$PrivateKeyPath = './priv.pem'
)

$header = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -InputObject @{
alg = "RS256"
typ = "JWT"
}))).TrimEnd('=').Replace('+', '-').Replace('/', '_');

$payload = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes((ConvertTo-Json -InputObject @{
iat = [System.DateTimeOffset]::UtcNow.AddSeconds(-30).ToUnixTimeSeconds()
exp = [System.DateTimeOffset]::UtcNow.AddMinutes(5).ToUnixTimeSeconds()
iss = $ClientId
}))).TrimEnd('=').Replace('+', '-').Replace('/', '_');

$rsa = [System.Security.Cryptography.RSA]::Create()
$rsa.ImportFromPem((Get-Content $PrivateKeyPath -Raw))

$signature = [Convert]::ToBase64String($rsa.SignData([System.Text.Encoding]::UTF8.GetBytes("$header.$payload"), [System.Security.Cryptography.HashAlgorithmName]::SHA256, [System.Security.Cryptography.RSASignaturePadding]::Pkcs1)).TrimEnd('=').Replace('+', '-').Replace('/', '_')
$jwt = "$header.$payload.$signature"

$presession = New-GithubSession -OrganizationName $OrganizationName -Token $jwt

$Installation = Invoke-GithubRestMethod -Session $presession -Path "app/installations"

if ($null -eq $Installation -or $Installation.Count -eq 0) {
throw "No installations found for the GitHub App in the organization '$OrganizationName'."
} elseif ($Installation.Count -gt 1) {
throw "Multiple installations found for the GitHub App in the organization '$OrganizationName'. Please specify a single installation."
}

$AccessToken = Invoke-GithubRestMethod -Session $presession -Path "app/installations/$($Installation.id)/access_tokens" -Method 'POST'

New-GithubSession -OrganizationName $OrganizationName -Token $AccessToken.token

}

function Invoke-GithubRestMethod {
[CmdletBinding()]
Expand All @@ -80,10 +129,10 @@ function Invoke-GithubRestMethod {
try {
do {
if($LinkHeader) {
$Response = Invoke-WebRequest -Uri "$LinkHeader" -Headers $Session.Headers -Method Get -ErrorAction Stop
$Response = Invoke-WebRequest -Uri "$LinkHeader" -Headers $Session.Headers -Method $Method -ErrorAction Stop
} else {
Write-Verbose "https://api.github.com/$($Path)"
$Response = Invoke-WebRequest -Uri "$($Session.Uri)$($Path)" -Headers $Session.Headers -Method Get -ErrorAction Stop
$Response = Invoke-WebRequest -Uri "$($Session.Uri)$($Path)" -Headers $Session.Headers -Method $Method -ErrorAction Stop
}

$Response.Content | ConvertFrom-Json | ForEach-Object { $_ }
Expand Down