Problem Context
PkgServer makes requests to GitHub to validate the registry repo URL on startup and to validate tree SHAs when fetching updates from the storage server, but it does not provide a way to supply a GitHub access token or other credentials to be used when making these requests for a private repo. This prevents use of PkgServer for private registries. Use of PkgServer for private registries is helpful to simplify access for users and continuous integration.
Proposal
Based on a discussion with @staticfloat, I'd like to propose adding PkgServer support for GitHub personal access tokens and use GitHub REST API endpoints for the two repository checks that PkgServer makes:
- add an optional
access_token member to RegistryMeta
- change the repository URL check to use
HEAD /repos/{owner}/{repository}
- change the tree SHA check to use
HEAD /repos/{owner}/{repository}/git/trees/{sha}
- if the token is not
nothing, add an HTTP Authorization header to the HEAD requests
I've validated that the above HEAD requests can be made with HTTP package, using tokens for private repos and no token for a public repo such as JuliaRegistries/General.
Implementation sketch
Add new functions, potentially scoped to a PkgServer sub module named GitHub
-
api_repository_url(repo_url::String)::String
Composes the GitHub API URL based on the GitHub repository URL. For example, for the General
registry, the repo and its API URL are:
https://github.com/JuliaRegistries/General.git -> https://api.github.com/repos/JuliaRegistries/General
-
api_tree_url(repo_base_url::String, sha::String)::String
Composes the GitHub API URL for a tree SHA. This URL can be used to validate that a tree SHA
exists in the upstream repository. repo_base_url is the API URL for the repository resource,
such as composed by api_repository_url(repo_url)
-
resource_exists(url::String; token::Union{Nothing,String}=nothing) -> Bool
Returns true if a HEAD request for the GitHub url returns a 200, false otherwise.
For non-public resources, specify a GitHub personal access token with the optional token
parameter (only GitHub REST API requests can be authorized with a token).
Add new members to RegistryMeta:
upstream_api_url::String - the base URL for the registry repo within the GitHub API path namespace
access_token::Union{Nothing,String} - the optional access token
Modify:
RegistryMeta constructor to accept an optional access token and generate/validate the upstream_api_url from the repository URL
verify_registry_hash(uuid::AbstractString, hash::AbstractString) to use the proposed functions to validate the tree SHA
Considerations
GitHub personal access tokens potentially grant broad privileges to multiple repos
- GitHub UI does not offer a way to generate a token that grants read-only repo access to a specific repository
- access is implicitly write if the user is authorized for write
- access spans all repos the user has access to
- to comply with principle of least privilege, an organization/individual setting up a private PkgServer would likely need to create a "machine account" with only read access to the private registry repo
OAuth or GitHub deployment keys might allow for finer-grained access control, but would require more restructuring of PkgServer.
Unit tests that do not perform network requests should be straightforward.
Integration tests that validate functionality with a private registry repo are desirable, but will likely require some
assistance/coordination
- setup a private repo under an appropriate Julia project organization
- write an integration test
- setup and validate the CI job
Problem Context
PkgServer makes requests to GitHub to validate the registry repo URL on startup and to validate tree SHAs when fetching updates from the storage server, but it does not provide a way to supply a GitHub access token or other credentials to be used when making these requests for a private repo. This prevents use of PkgServer for private registries. Use of PkgServer for private registries is helpful to simplify access for users and continuous integration.
Proposal
Based on a discussion with @staticfloat, I'd like to propose adding PkgServer support for GitHub personal access tokens and use GitHub REST API endpoints for the two repository checks that PkgServer makes:
access_tokenmember toRegistryMetaHEAD /repos/{owner}/{repository}HEAD /repos/{owner}/{repository}/git/trees/{sha}nothing, add an HTTPAuthorizationheader to the HEAD requestsI've validated that the above HEAD requests can be made with
HTTPpackage, using tokens for private repos and no token for a public repo such as JuliaRegistries/General.Implementation sketch
Add new functions, potentially scoped to a PkgServer sub module named
GitHubapi_repository_url(repo_url::String)::StringComposes the GitHub API URL based on the GitHub repository URL. For example, for the General
registry, the repo and its API URL are:
https://github.com/JuliaRegistries/General.git -> https://api.github.com/repos/JuliaRegistries/General
api_tree_url(repo_base_url::String, sha::String)::StringComposes the GitHub API URL for a tree SHA. This URL can be used to validate that a tree SHA
exists in the upstream repository.
repo_base_urlis the API URL for the repository resource,such as composed by
api_repository_url(repo_url)resource_exists(url::String; token::Union{Nothing,String}=nothing) -> BoolReturns
trueif aHEADrequest for the GitHuburlreturns a 200,falseotherwise.For non-public resources, specify a GitHub personal access token with the optional
tokenparameter (only GitHub REST API requests can be authorized with a token).
Add new members to
RegistryMeta:upstream_api_url::String- the base URL for the registry repo within the GitHub API path namespaceaccess_token::Union{Nothing,String}- the optional access tokenModify:
RegistryMetaconstructor to accept an optional access token and generate/validate theupstream_api_urlfrom the repository URLverify_registry_hash(uuid::AbstractString, hash::AbstractString)to use the proposed functions to validate the tree SHAConsiderations
GitHub personal access tokens potentially grant broad privileges to multiple repos
OAuth or GitHub deployment keys might allow for finer-grained access control, but would require more restructuring of PkgServer.
Unit tests that do not perform network requests should be straightforward.
Integration tests that validate functionality with a private registry repo are desirable, but will likely require some
assistance/coordination