conan-auth-source-plugin 0.0.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- auth_source/__init__.py +0 -0
- auth_source/auth_source_plugin.py +45 -0
- auth_source/authenticator.py +52 -0
- auth_source/config.py +81 -0
- auth_source/installer.py +55 -0
- auth_source/source_credentials.py +42 -0
- auth_source/types.py +38 -0
- auth_source_extensions/plugins/auth_source.py +28 -0
- conan_auth_source_plugin-0.0.5.dist-info/METADATA +164 -0
- conan_auth_source_plugin-0.0.5.dist-info/RECORD +14 -0
- conan_auth_source_plugin-0.0.5.dist-info/WHEEL +5 -0
- conan_auth_source_plugin-0.0.5.dist-info/entry_points.txt +2 -0
- conan_auth_source_plugin-0.0.5.dist-info/licenses/LICENSE +21 -0
- conan_auth_source_plugin-0.0.5.dist-info/top_level.txt +2 -0
auth_source/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The implementation of the auth source plugin
|
|
3
|
+
"""
|
|
4
|
+
import logging
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from auth_source.authenticator import AuthenticatorFactory
|
|
8
|
+
from auth_source.config import make_config
|
|
9
|
+
from auth_source.source_credentials import load_source_credentials, find_first_credentials
|
|
10
|
+
from auth_source.types import AuthSourceDetails
|
|
11
|
+
|
|
12
|
+
# A conan authentication plugin is not given the conan api or a logger, as it
|
|
13
|
+
# might cause recursion problems. Since the logger is not available, reach out
|
|
14
|
+
# and get the logger named conan.
|
|
15
|
+
logger = logging.getLogger("conan")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def plugin(url: str) -> Optional[AuthSourceDetails]:
|
|
19
|
+
"""
|
|
20
|
+
A Conan authentication for source credentials authenticator.
|
|
21
|
+
|
|
22
|
+
If the source URL is configured to support generating a github application token
|
|
23
|
+
then return a valid token.
|
|
24
|
+
"""
|
|
25
|
+
logging.debug("Loading 'source_credentials.json'")
|
|
26
|
+
source_credentials = load_source_credentials()
|
|
27
|
+
if source_credentials:
|
|
28
|
+
logging.info("Finding credentials for '%s'", url)
|
|
29
|
+
credentials = find_first_credentials(url, source_credentials)
|
|
30
|
+
if credentials:
|
|
31
|
+
config = make_config(credentials)
|
|
32
|
+
if config:
|
|
33
|
+
auth = AuthenticatorFactory.make_authenticator(url, config.type)
|
|
34
|
+
token = auth.make_token(config)
|
|
35
|
+
if token:
|
|
36
|
+
headers = credentials.get("headers")
|
|
37
|
+
return {"token": token, "headers": headers} if headers else {"token": token}
|
|
38
|
+
logger.warning("Failed to get github application token '%s'", url)
|
|
39
|
+
else:
|
|
40
|
+
logger.warning("Failed to make configuration for '%s'", url)
|
|
41
|
+
else:
|
|
42
|
+
logger.info("No 'source_credentials.json' configuration for '%s'", url)
|
|
43
|
+
else:
|
|
44
|
+
logger.warning("No 'source_credentials.json' found")
|
|
45
|
+
return None
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Plugable authenticator support
|
|
3
|
+
"""
|
|
4
|
+
import logging
|
|
5
|
+
from typing import Protocol, runtime_checkable, Optional
|
|
6
|
+
|
|
7
|
+
from github import GithubIntegration
|
|
8
|
+
|
|
9
|
+
from auth_source.config import Config
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger("conan")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@runtime_checkable
|
|
15
|
+
class Authenticator(Protocol):
|
|
16
|
+
"""
|
|
17
|
+
Interface for authenticator making an authentication token
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def make_token(self, config: Config) -> Optional[str]:
|
|
21
|
+
"""
|
|
22
|
+
Make a token given a configuration.
|
|
23
|
+
|
|
24
|
+
The token is a short-lived (1 hour) cryptographic string starting with 'ghs_'.
|
|
25
|
+
"""
|
|
26
|
+
...
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class GithubApplicationAuthenticator(Authenticator):
|
|
30
|
+
|
|
31
|
+
def make_token(self, config: Config) -> str:
|
|
32
|
+
"""
|
|
33
|
+
Create an authentication token for the given github application id.
|
|
34
|
+
"""
|
|
35
|
+
logger.info("GitHub App %d auth for Installation ID: %d", config.id, config.installation_id)
|
|
36
|
+
|
|
37
|
+
integration = GithubIntegration(config.id, config.private_key)
|
|
38
|
+
auth_connection = integration.get_access_token(config.installation_id)
|
|
39
|
+
return auth_connection.token
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class AuthenticatorFactory:
|
|
43
|
+
"""
|
|
44
|
+
A factory for making authentication instances. Only one so far...
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def make_authenticator(_url: str, _auth_type: Optional[str]) -> Authenticator:
|
|
49
|
+
"""
|
|
50
|
+
For now, only a github application authenticator is supported.
|
|
51
|
+
"""
|
|
52
|
+
return GithubApplicationAuthenticator()
|
auth_source/config.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Config POCO
|
|
3
|
+
"""
|
|
4
|
+
import os
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Optional, Any
|
|
7
|
+
|
|
8
|
+
from auth_source.types import CredentialBlock
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class Config:
|
|
13
|
+
"""
|
|
14
|
+
A top level state to hold command line arguments and program state.
|
|
15
|
+
"""
|
|
16
|
+
type: Optional[str]
|
|
17
|
+
"""
|
|
18
|
+
What type of authentication should be performed to get the token.
|
|
19
|
+
|
|
20
|
+
This is expected to be set if multiple authentication implementations are support. At
|
|
21
|
+
this stage this is a github application only provider, so the value is ignored (for now).
|
|
22
|
+
What we can see is that bitbucket self hosted doesn't support this style of auth (and a static
|
|
23
|
+
token is as good as it gets).
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
id: str | int
|
|
27
|
+
"""
|
|
28
|
+
The application id used for authentication.
|
|
29
|
+
|
|
30
|
+
Identifies your application globally to sign JSON Web Tokens (JWTs). This id is
|
|
31
|
+
generated by github when the application is created.
|
|
32
|
+
|
|
33
|
+
Note: This **not** the app name, the client id, or the app slug.
|
|
34
|
+
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
private_key: str
|
|
38
|
+
"""
|
|
39
|
+
A string containing the installation access
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
installation_id: int
|
|
43
|
+
"""
|
|
44
|
+
The installation id used for authentication.
|
|
45
|
+
|
|
46
|
+
Identifies a specific account (user/org) that installed your app. This is an integer that
|
|
47
|
+
is createdby github when a user installs the application.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def make_config(credential_block: Optional[CredentialBlock]) -> Optional[Config]:
|
|
52
|
+
"""
|
|
53
|
+
Create an authentication configuration for the given github application if possible.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
# If the credential block has a credential, then don't attempt to authenticate. It is assumed
|
|
57
|
+
# that a statically define token or user/password means we don't need to get an authentication token.
|
|
58
|
+
# Note: the main Conan logic requires a token or a user/password or headers. This might create
|
|
59
|
+
# an issue in the future and highlights how this plugin is using the `source_credentials.json`
|
|
60
|
+
# in an adhoc unapproved way.
|
|
61
|
+
if not credential_block.get("token") and not credential_block.get("user"):
|
|
62
|
+
|
|
63
|
+
app_id = _get_value_with_fallbacks(credential_block, "app_id", "CONAN_GITHUB_APP_ID")
|
|
64
|
+
private_key = _get_value_with_fallbacks(credential_block, "app_private_key", "CONAN_GITHUB_APP_PRIVATE_KEY")
|
|
65
|
+
installation_id = _get_value_with_fallbacks(credential_block, "app_installation_id",
|
|
66
|
+
"CONAN_GITHUB_APP_INSTALLATION_ID")
|
|
67
|
+
if all([app_id, private_key, installation_id]):
|
|
68
|
+
return Config(
|
|
69
|
+
type=credential_block.get("type"),
|
|
70
|
+
id=app_id,
|
|
71
|
+
private_key=private_key,
|
|
72
|
+
installation_id=installation_id)
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _get_value_with_fallbacks(data: Optional[CredentialBlock], data_name: str, primary_env: str) -> Optional[Any]:
|
|
77
|
+
"""
|
|
78
|
+
Checks a dictionary key, then a primary environment variable,
|
|
79
|
+
then a backup environment variable, defaulting to None.
|
|
80
|
+
"""
|
|
81
|
+
return data.get(data_name) or os.getenv(primary_env) or None
|
auth_source/installer.py
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A script to install the cci-build command into Conan.
|
|
3
|
+
"""
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
import shutil
|
|
7
|
+
from importlib.resources import files, as_file
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
log = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_conan_home() -> Path:
|
|
14
|
+
"""
|
|
15
|
+
Resolve Conan 2 home directory.
|
|
16
|
+
|
|
17
|
+
This is the root directory where Conan stores:
|
|
18
|
+
- cache
|
|
19
|
+
- extensions
|
|
20
|
+
- configuration
|
|
21
|
+
- remotes
|
|
22
|
+
|
|
23
|
+
Resolution order:
|
|
24
|
+
1. CONAN_HOME environment variable (if set)
|
|
25
|
+
2. Default platform-specific location (~/.conan2)
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
Path to Conan home directory.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
# 1. Explicit override (highest priority)
|
|
32
|
+
env_home = os.environ.get("CONAN_HOME")
|
|
33
|
+
if env_home:
|
|
34
|
+
return Path(env_home).expanduser().resolve()
|
|
35
|
+
|
|
36
|
+
# 2. Default Conan 2 home directory
|
|
37
|
+
# Conan 2 standard default is ~/.conan2 unless overridden
|
|
38
|
+
return Path.home() / ".conan2"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def main():
|
|
42
|
+
"""
|
|
43
|
+
Entry point for the conan auth source installer. This entry point is
|
|
44
|
+
installed by the setup.py script when the module is installed.
|
|
45
|
+
"""
|
|
46
|
+
conan_home = get_conan_home()
|
|
47
|
+
target_dir = conan_home / "extensions" / "plugins"
|
|
48
|
+
target_dir.mkdir(parents=True, exist_ok=True)
|
|
49
|
+
destination = target_dir / "auth_source.py"
|
|
50
|
+
|
|
51
|
+
resource = files("extensions.plugins").joinpath("auth_source.py")
|
|
52
|
+
with as_file(resource) as src:
|
|
53
|
+
shutil.copyfile(src, destination)
|
|
54
|
+
|
|
55
|
+
log.info("Installed Conan auth source plugin to '%s'", destination)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import platform
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from conan.errors import ConanException
|
|
7
|
+
from conan.internal.paths import get_conan_user_home
|
|
8
|
+
from conan.internal.util.files import load
|
|
9
|
+
from jinja2 import Template
|
|
10
|
+
|
|
11
|
+
from auth_source.types import SourceCredentials, CredentialBlock
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def load_source_credentials() -> Optional[SourceCredentials]:
|
|
15
|
+
"""
|
|
16
|
+
Reach out into Conan and load the source credentials file. This is not provided as a
|
|
17
|
+
plugin API parameter, so this needs to be loaded again. The `source_credentials.json`
|
|
18
|
+
file is a jinja2 template that must render as JSON.
|
|
19
|
+
"""
|
|
20
|
+
home_folder = get_conan_user_home()
|
|
21
|
+
creds_path = os.path.join(home_folder, "source_credentials.json")
|
|
22
|
+
if os.path.exists(creds_path):
|
|
23
|
+
try:
|
|
24
|
+
template = Template(load(creds_path))
|
|
25
|
+
content = template.render({"platform": platform, "os": os})
|
|
26
|
+
return json.loads(content)
|
|
27
|
+
except Exception as e:
|
|
28
|
+
raise ConanException(f"Error loading 'source_credentials.json' {creds_path}: {repr(e)}")
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def find_first_credentials(url: str, source_credentials: Optional[SourceCredentials]) -> Optional[CredentialBlock]:
|
|
33
|
+
"""
|
|
34
|
+
Find the first credential block that has a 'url' that is at the start of the source url.
|
|
35
|
+
"""
|
|
36
|
+
credentials_list = source_credentials.get("credentials", [])
|
|
37
|
+
for block in credentials_list:
|
|
38
|
+
# Extract the configuration URL pattern from the current block
|
|
39
|
+
config_url = block.get("url")
|
|
40
|
+
if config_url and url.startswith(config_url):
|
|
41
|
+
return block
|
|
42
|
+
return None # not found
|
auth_source/types.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python typing definitions.
|
|
3
|
+
"""
|
|
4
|
+
from typing import Dict, Optional, TypedDict, List
|
|
5
|
+
|
|
6
|
+
CredentialBlock = TypedDict(
|
|
7
|
+
"CredentialBlock",
|
|
8
|
+
{
|
|
9
|
+
"url": str,
|
|
10
|
+
"username": Optional[str],
|
|
11
|
+
"password": Optional[str],
|
|
12
|
+
"token": Optional[str],
|
|
13
|
+
"headers": Optional[Dict[str, str]],
|
|
14
|
+
"type": str,
|
|
15
|
+
|
|
16
|
+
"app_id": str,
|
|
17
|
+
"app_installation_id": Optional[str],
|
|
18
|
+
"app_private_key": Optional[str],
|
|
19
|
+
},
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# 2. Define the outer file layout without using a class
|
|
23
|
+
SourceCredentials = TypedDict(
|
|
24
|
+
"SourceCredentials",
|
|
25
|
+
{
|
|
26
|
+
"credentials": List[CredentialBlock]
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
AuthSourceDetails = TypedDict(
|
|
31
|
+
"AuthSourceDetails",
|
|
32
|
+
{
|
|
33
|
+
"token": Optional[str],
|
|
34
|
+
"username": Optional[str],
|
|
35
|
+
"password": Optional[str],
|
|
36
|
+
"headers": Optional[Dict[str, str]],
|
|
37
|
+
}
|
|
38
|
+
)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A Conan plugin module.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def auth_source_plugin(url: str, **kwargs):
|
|
7
|
+
"""
|
|
8
|
+
This is a conan plugin, that conforms to the plugin definition in Conan.
|
|
9
|
+
|
|
10
|
+
This implementation thunks the call through to the plugin entry point
|
|
11
|
+
in the Conan auth source authentication plugin module.
|
|
12
|
+
|
|
13
|
+
In the current implementation, defined here:
|
|
14
|
+
- https://github.com/conan-io/conan/blob/develop2/conan/internal/rest/conan_requester.py#L66
|
|
15
|
+
|
|
16
|
+
At the time of writing, Conan invokes this plugin with the request URL and
|
|
17
|
+
no additional keyword arguments. Perhaps in the future Conan could pass:
|
|
18
|
+
- a logger instance
|
|
19
|
+
- the best matching section of the `source_credentials.json` file, or the whole contents
|
|
20
|
+
- the `www-authenticate` headers upon a 401 request failing
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
# Import the python module at this point, so that module loading issues
|
|
24
|
+
# are reported during authentication.
|
|
25
|
+
#
|
|
26
|
+
# pylint: disable=import-outside-toplevel
|
|
27
|
+
from auth_source.auth_source_plugin import plugin
|
|
28
|
+
return plugin(url, **kwargs)
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: conan-auth-source-plugin
|
|
3
|
+
Version: 0.0.5
|
|
4
|
+
Summary: A python module to provide GitHub application authorisation for source downloads
|
|
5
|
+
Requires-Python: >=3.13
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: conan<3.0,>=2.25
|
|
9
|
+
Requires-Dist: packaging>=26.2
|
|
10
|
+
Requires-Dist: PyGithub>=2.9.1
|
|
11
|
+
Dynamic: description
|
|
12
|
+
Dynamic: description-content-type
|
|
13
|
+
Dynamic: license-file
|
|
14
|
+
Dynamic: requires-dist
|
|
15
|
+
Dynamic: requires-python
|
|
16
|
+
Dynamic: summary
|
|
17
|
+
|
|
18
|
+
# [conan-auth-source-plugin](https://github.com/conan-py/conan-auth-source-plugin)
|
|
19
|
+
|
|
20
|
+
A Conan authentication source plugin, implemented as a python module. Conan supports both a *remote*
|
|
21
|
+
and a *source* authentication, where the remotes are used for interacting with a remote for
|
|
22
|
+
packages, whereas the *source* is used for getting source using the `get()` or `download()`
|
|
23
|
+
method in a `conanfile.py`.
|
|
24
|
+
|
|
25
|
+
# Installation
|
|
26
|
+
|
|
27
|
+
Install the conan authentication source Python module, then install the plugin in that module
|
|
28
|
+
into the conan installation.
|
|
29
|
+
|
|
30
|
+
```shell
|
|
31
|
+
python -m pip install conan-auth-source-plugin
|
|
32
|
+
conan-auth-source-plugin-install
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
# Configuration
|
|
36
|
+
|
|
37
|
+
This plugin uses the
|
|
38
|
+
[`source_creditials.json`](https://docs.conan.io/2/reference/config_files/source_credentials.html)
|
|
39
|
+
file for configuration. This file is marked as experimental at this stage. This module further
|
|
40
|
+
experiments and extends its usage.
|
|
41
|
+
|
|
42
|
+
**Note**: The conan source configuration code uses a first match (begins with) strategy with URLs.
|
|
43
|
+
Thus, it is important to order the credentials in longest url first if there is any overlap in
|
|
44
|
+
matching the URL being fetched with the configuration.
|
|
45
|
+
|
|
46
|
+
## Sample
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"credentials": [
|
|
51
|
+
{
|
|
52
|
+
"url": "https://github.com/...",
|
|
53
|
+
"type": "github.app",
|
|
54
|
+
"app_id": "4459267",
|
|
55
|
+
"app_installation_id": "150620648",
|
|
56
|
+
"app_private_key" : "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
# Create App
|
|
63
|
+
|
|
64
|
+
The following procedure can be used to create an application in github. This procedure requires an
|
|
65
|
+
organisation owner, or a team member with app management permissions.
|
|
66
|
+
|
|
67
|
+
This procedure is documented as a GitHub app that act on their
|
|
68
|
+
[own behalf](https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps#github-apps-that-act-on-their-own-behalf).
|
|
69
|
+
This requires an installation access token for authentication.
|
|
70
|
+
|
|
71
|
+
1. Go to the organisation (or user) settings
|
|
72
|
+
|
|
73
|
+
https://github.com/organizations/conan-py/settings/apps
|
|
74
|
+
https://github.com/<org name>/conan-py/settings/apps
|
|
75
|
+
|
|
76
|
+
2. App settings
|
|
77
|
+
|
|
78
|
+
- provide a github app name
|
|
79
|
+
- write a description
|
|
80
|
+
- add a homepage URL (e.g. to the organisation landing page), even though it isn't explicitly used
|
|
81
|
+
- disable web hook
|
|
82
|
+
- add repository permission 'Contents', set to 'Read-Only'
|
|
83
|
+
|
|
84
|
+
3. Once the app is created, the 'App ID' and the 'Client ID' (not used for this workflow) are known
|
|
85
|
+
|
|
86
|
+
4. Go to the bottom of the application and generate a private key. This will
|
|
87
|
+
generate a 2048bit RSA key pair without a pass phrase.
|
|
88
|
+
|
|
89
|
+
5. On the side bar of the application, select the "Install App" menu item. Once installed
|
|
90
|
+
the installation id can be taken from the installation URL. For example if the installation
|
|
91
|
+
URL is 'https://github.com/organizations/conan-py/settings/installations/150620648', then the
|
|
92
|
+
installation id is 150620648. The installation id is not displayed in the web UI of github.
|
|
93
|
+
|
|
94
|
+
# Why use this plugin module
|
|
95
|
+
|
|
96
|
+
This module is a shift-left style strategy for authentication. Instead of using this pluing
|
|
97
|
+
a build pipeline (or any Conan build) can pre-authenticate with all github organisation/repositores
|
|
98
|
+
that *may* be needed during a build.
|
|
99
|
+
|
|
100
|
+
This module goes half-way towards "authentication on demand". This is a concept where http
|
|
101
|
+
authentication is only attempted by a client if a
|
|
102
|
+
[401 (Not authenticated)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/401)
|
|
103
|
+
response is received, and the
|
|
104
|
+
[`WWW-Authenticate` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/WWW-Authenticate)
|
|
105
|
+
provides
|
|
106
|
+
[authentication schemes](https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml)
|
|
107
|
+
that are semantically understood by the client. Once authenticated the client should reissue the
|
|
108
|
+
http request with the new credentials.
|
|
109
|
+
|
|
110
|
+
*Residual*: This plugin does not defer authentication until after it is needed. This is not
|
|
111
|
+
supported by the Conan client.
|
|
112
|
+
|
|
113
|
+
# Known issues
|
|
114
|
+
|
|
115
|
+
- this implementation stores private keys by value in memory. e.g. if using AWS it
|
|
116
|
+
would be better to use a HSM or AWS KMS, but this would require an implementation
|
|
117
|
+
of the `github.Auth.Auth` class. Using AWS Secrets Manager at least stores the
|
|
118
|
+
key more securely at rest, even though it will be stored in memory non-securely.
|
|
119
|
+
|
|
120
|
+
- when using the `get()` method in a `conanfile.py`, provide a filename parameter
|
|
121
|
+
with a representative name (e.g. 'archive.tgz') so that conan can write the download
|
|
122
|
+
to disk. The filename should be expressed in the `conandat.yml`.
|
|
123
|
+
|
|
124
|
+
# Development
|
|
125
|
+
|
|
126
|
+
To install the plugin in a local Conan environment, the whole of the plugin repository
|
|
127
|
+
can be installed, as the `.conanignore` will exclude everything except the plugin
|
|
128
|
+
python file that thunks to the module.
|
|
129
|
+
|
|
130
|
+
```shell
|
|
131
|
+
conan config install .
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Install the plugin Python for development as an editable module. From the root of the
|
|
135
|
+
repository/project:
|
|
136
|
+
|
|
137
|
+
```shell
|
|
138
|
+
pip install --editable .
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
# Links
|
|
142
|
+
|
|
143
|
+
- https://pypi.org/project/conan-auth-source-plugin
|
|
144
|
+
- https://github.com/conan-io/conan-extensions/tree/main
|
|
145
|
+
- https://docs.conan.io/2/reference/extensions/authorization_plugins.html
|
|
146
|
+
- https://docs.conan.io/2/reference/config_files/source_credentials.html
|
|
147
|
+
- https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/about-authentication-with-a-github-app
|
|
148
|
+
- https://docs.github.com/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps
|
|
149
|
+
|
|
150
|
+
## pygithub
|
|
151
|
+
|
|
152
|
+
- https://github.com/PyGithub/PyGithub/tree/main
|
|
153
|
+
- https://pygithub.readthedocs.io/en/stable/introduction.html
|
|
154
|
+
|
|
155
|
+
# Appendices
|
|
156
|
+
|
|
157
|
+
## github tarball URLs
|
|
158
|
+
|
|
159
|
+
For getting source from a private github repo, use a URL/http request of the form:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
GET https://api.github.com/repos/{owner}/{repo}/tarball/{ref}
|
|
163
|
+
Authorization: Bearer <installation_token>
|
|
164
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
auth_source/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
auth_source/auth_source_plugin.py,sha256=PcoW-23hVg0WB5u-T2TmmdOrYdF_zkgtmsavsKcpg_o,1861
|
|
3
|
+
auth_source/authenticator.py,sha256=o9OElnlNOsGfUwjs42QKV3qd-aPf_ayH0wCk9M2jlIA,1467
|
|
4
|
+
auth_source/config.py,sha256=gWwM3iw29A2C5nHNtHtxVJh7Kp6hCfk4Um_c80EJMoc,3137
|
|
5
|
+
auth_source/installer.py,sha256=LrxtkpMI-ubmlaPZKazhbuh8bDlDxRhHOduDwvi_cys,1539
|
|
6
|
+
auth_source/source_credentials.py,sha256=YduTSilKECR6I33eF6OIpUVNVNqmfmolW7PikhKhqkc,1639
|
|
7
|
+
auth_source/types.py,sha256=e7GuJF5X0XKHFzfS0ADoq95x6ncQ5oGeBHdW2OOIOuA,848
|
|
8
|
+
auth_source_extensions/plugins/auth_source.py,sha256=9xok3PYVQVub1bA-slPksvd5U7lQseLolHPt4tqlePc,1102
|
|
9
|
+
conan_auth_source_plugin-0.0.5.dist-info/licenses/LICENSE,sha256=P9a82Ofi3oMxuvQ85tZT84Un2FYz9yHndiwP2XIBzqQ,1117
|
|
10
|
+
conan_auth_source_plugin-0.0.5.dist-info/METADATA,sha256=9vFHhBlrY6fHzJhi3ySrI3z7PT9szViMJuYBD-gbZf8,6316
|
|
11
|
+
conan_auth_source_plugin-0.0.5.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
12
|
+
conan_auth_source_plugin-0.0.5.dist-info/entry_points.txt,sha256=rzPCZZ5__pTwem1OZmaJ6Ufk0BoKZa3igq36rc0NkrA,80
|
|
13
|
+
conan_auth_source_plugin-0.0.5.dist-info/top_level.txt,sha256=uYNHnySICBwxjdmitoWBFvHVSfesW-1YGhZWxPB7SkM,35
|
|
14
|
+
conan_auth_source_plugin-0.0.5.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Utilties, plugins and extesions for Conan package management
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|