• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ansible / awx-plugins / 22356707979

24 Feb 2026 03:05PM UTC coverage: 72.473% (+0.2%) from 72.308%
22356707979

Pull #160

github

web-flow
Merge de903295d into 80291c0b7
Pull Request #160: ⛓🔒 Bump transitive deps in pip-tools-managed lockfiles

37 of 37 branches covered (100.0%)

Branch coverage included in aggregate %.

2372 of 3287 relevant lines covered (72.16%)

2.16 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.92
/src/awx_plugins/credentials/github_app.py
1
"""GitHub App Installation Access Token Credential Plugin.
2

3
This module defines a credential plugin for making use of the
4
GitHub Apps mechanism, allowing authentication via GitHub App
5
installation-scoped access tokens.
6

7
Functions:
8

9
- :func:`extract_github_app_install_token`: Generates a GitHub App
10
  Installation token.
11
- ``github_app_lookup``: Defines the credential plugin interface.
12
"""
13

14
from typing import TypedDict, Unpack
3✔
15

16
from awx_plugins.interfaces._temporary_private_django_api import (  # noqa: WPS436
3✔
17
    gettext_noop as _,
18
)
19

20
from github import (
3✔
21
    Auth as Auth,
22
    Github,
23
)
24
from github.Consts import DEFAULT_BASE_URL as PUBLIC_GH_API_URL
3✔
25
from github.GithubException import (
3✔
26
    BadAttributeException,
27
    GithubException,
28
    UnknownObjectException,
29
)
30

31
from . import _types
3✔
32
from .plugin import CredentialPlugin
3✔
33

34

35
__all__ = ('github_app_lookup',)  # noqa: WPS410
3✔
36

37

38
github_app_inputs: _types.PluginInputs = {
3✔
39
    'fields': [
3✔
40
        {
41
            'id': 'github_api_url',
3✔
42
            'label': _('GitHub API endpoint URL'),
×
43
            'type': 'string',
3✔
44
            'help_text': _(
×
45
                'Specify the GitHub API URL here. In the case of an Enterprise: '
3✔
46
                'https://gh.your.org/api/v3 (self-hosted) '
47
                'or https://api.SUBDOMAIN.ghe.com (cloud)',
48
            ),
49
            'default': 'https://api.github.com',
3✔
50
        },
51
        {
52
            'id': 'app_or_client_id',
3✔
53
            'label': _('GitHub App ID or Client ID'),
×
54
            'type': 'string',
3✔
55
            'help_text': _(
×
56
                'The GitHub App ID or Client ID created by the GitHub Admin. '
3✔
57
                'Example App ID: 1121547, Client ID: Iv23likIfIXeZTb5GCAA '
58
                'found on https://github.com/settings/apps/ '
59
                'required for creating a JWT token for authentication.',
60
            ),
61
        },
62
        {
63
            'id': 'install_id',
3✔
64
            'label': _('GitHub App Installation ID'),
×
65
            'type': 'string',
3✔
66
            'help_text': _(
×
67
                'The Installation ID from the GitHub App installation '
3✔
68
                'generated by the GitHub Admin. '
69
                'Example: 59980338 extracted from the installation link '
70
                'https://github.com/settings/installations/59980338 '
71
                'required for creating a limited GitHub app token.',
72
            ),
73
        },
74
        {
75
            'id': 'private_rsa_key',
3✔
76
            'label': _('RSA Private Key'),
×
77
            'type': 'string',
3✔
78
            # `ssh_private_key` validator checks for PKCS#1 PEM-like formats
79
            'format': 'ssh_private_key',
3✔
80
            'secret': True,
3✔
81
            'multiline': True,
3✔
82
            'help_text': _(
×
83
                'Paste the contents of the PEM file that the GitHub Admin '
3✔
84
                'provided to you with the app and installation IDs.',
85
            ),
86
        },
87
    ],
88
    'metadata': [
3✔
89
        {
90
            'id': 'description',
3✔
91
            'label': _('Description (Optional)'),
×
92
            'type': 'string',
3✔
93
            'help_text': _('To be removed after UI is updated'),
×
94
        },
95
    ],
96
    'required': ['app_or_client_id', 'install_id', 'private_rsa_key'],
3✔
97
}
98

99

100
class EmptyKwargs(TypedDict):
3✔
101
    """Schema for zero keyword arguments."""
102

103

104
def extract_github_app_install_token(  # noqa: WPS210
3✔
105
    *,
106
    github_api_url: str,
107
    app_or_client_id: int | str,
108
    private_rsa_key: str,
109
    install_id: int | str,
110
    **_discarded_kwargs: Unpack[EmptyKwargs],
111
) -> str:
112
    """Generate a GH App Installation access token.
113

114
    :param github_api_url: The GitHub instance API endpoint URL.
115
    :param app_or_client_id: The GitHub App ID or Client ID.
116
    :param private_rsa_key: The private key associated with the GitHub
117
        App.
118
    :param install_id: The GitHub App Installation ID.
119
    :param _discarded_kwargs: Aren't expected to be passed.
120
    :returns: A GitHub access token for a GitHub App Installation.
121
    :raises ValueError: If authentication fails or parameters are invalid.
122
    :raises RuntimeError: If an unexpected error occurs during token generation.
123
    """
124
    auth = Auth.AppAuth(
3✔
125
        app_id=str(app_or_client_id),
3✔
126
        private_key=private_rsa_key,
3✔
127
    ).get_installation_auth(installation_id=int(install_id))
3✔
128

129
    Github(  # Generate a GitHub App authentication token
3✔
130
        auth=auth,
3✔
131
        base_url=github_api_url or PUBLIC_GH_API_URL,
3✔
132
    )
133

134
    doc_url = (
3✔
135
        'See https://docs.github.com/rest/reference/apps'
3✔
136
        '#create-an-installation-access-token-for-an-app'
137
    )
138
    app_install_context = (
3✔
139
        f'app_or_client_id: {app_or_client_id}, install_id: {install_id}'
3✔
140
    )
141

142
    try:
143
        return auth.token
3✔
144
    # NOTE: Exceptions coming from PyGitHub have `Any` in the base exception
145
    # NOTE: initializer. This trips MyPy's `disallow_any_expr` check even
146
    # NOTE: though it's not in our code. This is why we ignore `misc` in the
147
    # NOTE: except blocks below.
148
    #
149
    # Ref:
150
    # * https://github.com/PyGithub/PyGithub/issues/3218
151
    # * https://github.com/PyGithub/PyGithub/blob/038624c/github\
152
    #   /GithubException.py#L56
153
    except (
3✔
154
        UnknownObjectException  # type: ignore[misc]
3✔
155
    ) as github_install_not_found_exc:
156
        raise ValueError(
3✔
157
            'Failed to retrieve a GitHub installation token from '
3✔
158
            f'{github_api_url!s} using {app_install_context!s}. '
159
            f'Is the app installed? {doc_url!s}.'
160
            f'\n\n{github_install_not_found_exc!s}',
161
        ) from github_install_not_found_exc
3✔
162
    except GithubException as pygithub_catchall_exc:  # type: ignore[misc]
3✔
163
        raise RuntimeError(
3✔
164
            'An unexpected error happened while talking to GitHub API @ '
3✔
165
            f'{github_api_url!s} ({app_install_context!s}). '
166
            'Is the app or client ID correct? And the private RSA key? '
167
            f'{doc_url!s}.\n\n{pygithub_catchall_exc!s}',
168
        ) from pygithub_catchall_exc
3✔
169
    except BadAttributeException as github_broken_exc:  # type: ignore[misc]
3✔
170
        raise RuntimeError(
3✔
171
            f'Broken GitHub @ {github_api_url!s} with '
3✔
172
            f'{app_install_context!s}. It is a bug, please report it to the '
173
            f'developers.\n\n{github_broken_exc!s}',
174
        ) from github_broken_exc
3✔
175

176

177
github_app_lookup = CredentialPlugin(
3✔
178
    'GitHub App Installation Access Token Lookup',
3✔
179
    inputs=github_app_inputs,
3✔
180
    backend=extract_github_app_install_token,
3✔
181
)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc