Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:

steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/contributors_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
issues: write
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
# If you do not check out your code, Copilot will do this for you.
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docker-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/mark-ready-when-ready.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
github.event.pull_request.draft == true
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/python-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
python-version: [3.11, 3.12, 3.13, 3.14]
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:

steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/stale.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
pull-requests: read
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/super-linter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:

steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit

Expand Down
14 changes: 8 additions & 6 deletions auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def auth_to_github(
else:
gh = github3.github.GitHub()
gh.login_as_app_installation(
gh_app_private_key_bytes, gh_app_id, gh_app_installation_id
gh_app_private_key_bytes, str(gh_app_id), gh_app_installation_id
)
github_connection = gh
elif ghe and token:
Expand All @@ -51,24 +51,26 @@ def auth_to_github(

def get_github_app_installation_token(
ghe: str,
gh_app_id: str,
gh_app_id: int | None,
gh_app_private_key_bytes: bytes,
gh_app_installation_id: str,
gh_app_installation_id: int | None,
) -> str | None:
"""
Get a GitHub App Installation token.
API: https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation

Args:
ghe (str): the GitHub Enterprise endpoint
gh_app_id (str): the GitHub App ID
gh_app_id (int | None): the GitHub App ID
gh_app_private_key_bytes (bytes): the GitHub App Private Key
gh_app_installation_id (str): the GitHub App Installation ID
gh_app_installation_id (int | None): the GitHub App Installation ID

Returns:
str: the GitHub App token
"""
jwt_headers = github3.apps.create_jwt_headers(gh_app_private_key_bytes, gh_app_id)
jwt_headers = github3.apps.create_jwt_headers(
gh_app_private_key_bytes, str(gh_app_id)
)
api_endpoint = f"{ghe}/api/v3" if ghe else "https://api.github.com"
url = f"{api_endpoint}/app/installations/{gh_app_installation_id}/access_tokens"

Expand Down
34 changes: 30 additions & 4 deletions test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ def test_auth_to_github_with_ghe_and_ghe_app(self, mock_ghe):
mock = mock_ghe.return_value
mock.login_as_app_installation = MagicMock(return_value=True)
result = auth.auth_to_github(
"", "123", "123", b"123", "https://github.example.com", True
"", 123, 456, b"123", "https://github.example.com", True
)
mock.login_as_app_installation.assert_called_once()
mock.login_as_app_installation.assert_called_once_with(b"123", "123", 456)
self.assertEqual(result, mock)

@patch("github3.github.GitHub")
Expand All @@ -69,9 +69,9 @@ def test_auth_to_github_with_app(self, mock_gh):
mock = mock_gh.return_value
mock.login_as_app_installation = MagicMock(return_value=True)
result = auth.auth_to_github(
"", "123", "123", b"123", "https://github.example.com", False
"", 123, 456, b"123", "https://github.example.com", False
)
mock.login_as_app_installation.assert_called_once()
mock.login_as_app_installation.assert_called_once_with(b"123", "123", 456)
self.assertEqual(result, mock)

@patch("github3.apps.create_jwt_headers", MagicMock(return_value="gh_token"))
Expand All @@ -92,6 +92,32 @@ def test_get_github_app_installation_token(self, mock_post):

self.assertEqual(result, dummy_token)

@patch(
"github3.apps.create_jwt_headers",
return_value={"Authorization": "Bearer gh_token"},
)
@patch("requests.post")
def test_get_github_app_installation_token_casts_int_app_id_to_str(
self, mock_post, mock_create_jwt
):
"""
Test that get_github_app_installation_token casts an int gh_app_id to str
before passing it to create_jwt_headers (PyJWT requires iss to be a string).
"""
mock_response = MagicMock()
mock_response.raise_for_status.return_value = None
mock_response.json.return_value = {"token": "dummytoken"}
mock_post.return_value = mock_response

auth.get_github_app_installation_token(
ghe="",
gh_app_id=12345,
gh_app_private_key_bytes=b"private_key",
gh_app_installation_id=678910,
)

mock_create_jwt.assert_called_once_with(b"private_key", "12345")

@patch("github3.apps.create_jwt_headers", MagicMock(return_value="gh_token"))
@patch("auth.requests.post")
def test_get_github_app_installation_token_request_failure(self, mock_post):
Expand Down
Loading