-
Notifications
You must be signed in to change notification settings - Fork 310
HPCC-35979 feat(eclccserver) Add github app support to eclccserver #21189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ghalliday
wants to merge
1
commit into
hpcc-systems:candidate-10.0.x
Choose a base branch
from
ghalliday:issue35979
base: candidate-10.0.x
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| # Using GitHub apps for authenticating from eclccserver | ||
|
|
||
| ## Creating and Configuring a GitHub App for eclccserver | ||
|
|
||
| Here is a step-by-step guide to creating and configuring a GitHub App to use with the authentication mechanism. | ||
|
|
||
| ### Step 1: Create the GitHub App | ||
| 1. Go to your GitHub account (or Organization) **Settings**. | ||
| 2. On the left sidebar, scroll down and click **Developer settings**. | ||
| 3. Select **GitHub Apps** in the left sidebar, then click the **New GitHub App** button. | ||
| 4. Fill out the **Register new GitHub App** form: | ||
| * **GitHub App name**: Give it a recognizable name (e.g., `HPCC ECL Fetcher`). | ||
| * **Homepage URL**: You can use your organization's URL or the HPCC platform repository URL (this is just required by the form). | ||
| * **Webhook**: Uncheck the **Active** checkbox. (HPCC only needs to pull code; it doesn't need to listen for GitHub events). | ||
| 5. Set the **Repository permissions**: | ||
| * Under **Repository permissions**, find **Contents** and set the access to **Read-only**. (This gives the app permission to perform `git fetch` / `git clone`). | ||
| 6. Scroll to the bottom (**Where can this GitHub App be installed?**): | ||
| * Select **Any account** if you plan to fetch repositories owned by different organizations/users. Select **Only on this account** if you exclusively fetch repositories within your current organization. | ||
| 7. Click **Create GitHub App**. | ||
|
|
||
| ### Step 2: Gather Your Secrets | ||
| Immediately after creating the app, you will land on its settings page. You need to collect three items to populate your HPCC secrets configuration: | ||
|
|
||
| 1. **The App ID** (`appid`): | ||
| * Look at the "About" section at the top of the page. Copy the **App ID**. | ||
| 2. **The Private Key** (`appkey`): | ||
| * Scroll down to the **Private keys** section. | ||
| * Click **Generate a private key**. | ||
| * This will download a `.pem` file to your computer. The entire contents of this file (including the `-----BEGIN RSA PRIVATE KEY-----` and end tags) will be your `appkey` secret. | ||
|
|
||
| ### Step 3: Install the App & Get the Installation ID | ||
| The App ID and Private Key alone are not enough; the app must be *installed* on the target account/repository to generate the `installationid`. | ||
|
|
||
| 1. While still on the App's settings page, click **Install App** on the left sidebar. | ||
| 2. Click **Install** next to the user or organization account where the target ECL repositories live. | ||
| 3. Choose whether to install it on **All repositories** or **Only select repositories**, then click **Install**. | ||
| 4. You will be redirected to the installation settings page. Look at the URL in your browser's address bar. It will look like this: | ||
| `https://github.com/settings/installations/12345678` | ||
| or | ||
| `https://github.com/organizations/YOUR_ORG/settings/installations/12345678` | ||
| 5. Copy the numeric value at the end of the URL (e.g., `12345678`). This is your **Installation ID** (`installationid`). | ||
|
|
||
| ## Configuring the secrets for eclccserver | ||
|
|
||
| 1. configure the git user name to be x-access-token | ||
|
|
||
| 2. Create a secret category "git", secret "x-access-token" | ||
|
|
||
| 3. Place these three values highlighted above (`appid`, `appkey`, and `installationid`) into your HPCC secret. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,6 +49,20 @@ | |
| #pragma GCC diagnostic pop | ||
| #endif | ||
|
|
||
| #ifdef verify | ||
| #define JWT_HAS_VERIFY_MACRO | ||
| #define OLD_VERIFY verify | ||
| #undef verify | ||
| #endif | ||
|
|
||
| #include "jwt-cpp/jwt.h" | ||
| #include "nlohmann/json.hpp" | ||
|
|
||
| #ifdef JWT_HAS_VERIFY_MACRO | ||
| //Force an error if verify macro is used in any of the following code | ||
| #undef verify | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This may be just a matter of opinion, but disabling the macro like this is a little odd. I don't think verify is used much at all in the platform, but I also don't think it is outright undefined anywhere else so this becomes potentially new behavior during compilation. |
||
| #endif | ||
|
|
||
| #ifdef _USE_OPENSSL | ||
| #include <opensslcommon.hpp> | ||
| #include <openssl/x509v3.h> | ||
|
|
@@ -2427,3 +2441,70 @@ void maskSecret(StringBuffer & maskedSecret, const char * originalSecret, unsign | |
| maskedSecret.append(originalSecret[i]); | ||
| } | ||
| } | ||
|
|
||
| std::string generateGithubIAT(const char * appId, const char * appKey, const char * installationId) | ||
| { | ||
| try | ||
| { | ||
| auto now = std::chrono::system_clock::now(); | ||
| auto token = jwt::create() | ||
| .set_issuer(appId) | ||
| .set_issued_at(now) | ||
| .set_expires_at(now + std::chrono::minutes(10)) | ||
| .sign(jwt::algorithm::rs256("", appKey)); | ||
|
|
||
| httplib::SSLClient cli("api.github.com"); | ||
| cli.set_bearer_token_auth(token.c_str()); | ||
| cli.set_default_headers({ | ||
| {"User-Agent", "ECL-Compiler/1.0"}, | ||
| {"Accept", "application/vnd.github.v3+json"} | ||
| }); | ||
|
|
||
| // Generate Access Token | ||
| std::string tokenPath = "/app/installations/"; | ||
| tokenPath += installationId; | ||
| tokenPath += "/access_tokens"; | ||
| auto postRes = cli.Post(tokenPath.c_str()); | ||
| if (!postRes || postRes->status != 201) | ||
| { | ||
| DBGLOG("Failed to generate GitHub IAT. HTTP status: %d", postRes ? postRes->status : -1); | ||
| return ""; | ||
| } | ||
|
|
||
| auto tokenJson = nlohmann::json::parse(postRes->body); | ||
| return tokenJson["token"].get<std::string>(); | ||
| } | ||
| catch (const std::exception& e) | ||
| { | ||
| DBGLOG("Exception generating GitHub IAT: %s", e.what()); | ||
| } | ||
|
|
||
| return ""; | ||
| } | ||
|
|
||
| IFile * getFileWithGitAccessToken(const char * gitUser) | ||
| { | ||
| Owned<const IPropertyTree> secret = getSecret("git", gitUser); | ||
| if (!secret) | ||
| { | ||
| DBGLOG("No secret found for git user %s", gitUser); | ||
| return nullptr; | ||
| } | ||
|
|
||
| MemoryBuffer gitKey; | ||
| if (getSecretKeyValue(gitKey, secret, "password")) | ||
| return writeToProtectedTempFile("eclcc", "git", gitKey.length(), gitKey.toByteArray()); | ||
|
|
||
| StringBuffer appId, appKey, installationId; | ||
| if (getSecretKeyValue(appId, secret, "appid") && getSecretKeyValue(appKey, secret, "appkey") && getSecretKeyValue(installationId, secret, "installationid")) | ||
| { | ||
| // Generate an Installation Access Token (IAT) from the App ID, Private Key, and Installation ID | ||
| std::string iat = generateGithubIAT(appId.str(), appKey.str(), installationId.str()); | ||
| if (!iat.empty()) | ||
| return writeToProtectedTempFile("eclcc", "git", iat.length(), iat.c_str()); | ||
| return nullptr; | ||
| } | ||
|
|
||
| DBGLOG("Secret doesn't contain password or github app credentials for git user %s", gitUser); | ||
| return nullptr; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should you reinstate the old verify? The code at system/security/plugins/jwtSecurity/jwtSecurity.cpp does, near the end:
I think it is only strictly necessary if any code within this file needs the original value of
verify, but I wonder if it should be reinstated after all JWT calls simply in order to avoid invisible tech debt.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think copilot cloned this - I will update