Skip to content
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

NIFI-13231 Added Private key authentication for GitHubFlowRegistryClient #8890

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
NIFI-13231 Made the changes requested
  • Loading branch information
vanshks1132 committed May 31, 2024
commit 28dbc57f507418edd3f1093304d345d1cc3d79b6
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ public enum GitHubAuthenticationType {
NONE,
PERSONAL_ACCESS_TOKEN,
APP_INSTALLATION_TOKEN,
PRIVATE_KEY;
APP_INSTALLATION_ID_AND_PRIVATE_KEY;

}
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,19 @@ public class GitHubFlowRegistryClient extends AbstractFlowRegistryClient {
.build();
static final PropertyDescriptor PRIVATE_KEY = new PropertyDescriptor.Builder()
.name("Private Key")
.description("Private RSA key generated foo Github App to use for Authentication")
.description("RSA private key associated with GitHub App to use for authentication.")
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.required(true)
.sensitive(true)
.dependsOn(AUTHENTICATION_TYPE, GitHubAuthenticationType.PRIVATE_KEY.name())
.dependsOn(AUTHENTICATION_TYPE, GitHubAuthenticationType.APP_INSTALLATION_ID_AND_PRIVATE_KEY.name())
.build();
static final PropertyDescriptor APP_ID = new PropertyDescriptor.Builder()
.name("APP ID")
.description("App Id of Github App to use for Authentication")
.name("App ID")
.description("Identifier of GitHub App to use for authentication")
.addValidator(StandardValidators.NON_BLANK_VALIDATOR)
.required(true)
.sensitive(true)
.dependsOn(AUTHENTICATION_TYPE, GitHubAuthenticationType.PRIVATE_KEY.name())
.sensitive(false)
.dependsOn(AUTHENTICATION_TYPE, GitHubAuthenticationType.APP_INSTALLATION_ID_AND_PRIVATE_KEY.name())
.build();
static final List<PropertyDescriptor> PROPERTY_DESCRIPTORS = List.of(
GITHUB_API_URL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;
import org.kohsuke.github.GitHubBuilder;
import org.kohsuke.github.extras.authorization.JWTTokenProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -80,11 +81,13 @@ private GitHubRepositoryClient(final Builder builder) throws IOException, FlowRe
switch (authenticationType) {
case PERSONAL_ACCESS_TOKEN -> gitHubBuilder.withOAuthToken(builder.personalAccessToken);
case APP_INSTALLATION_TOKEN -> gitHubBuilder.withAppInstallationToken(builder.appInstallationToken);
case PRIVATE_KEY -> {
case APP_INSTALLATION_ID_AND_PRIVATE_KEY -> {
try {
gitHubBuilder.withJwtToken(loadPrivateKeyFromPEM(builder().privateKey));
JWTTokenProvider jwtTokenProvider = new JWTTokenProvider(builder().appId, builder().privateKey);
String token = jwtTokenProvider.getEncodedAuthorization();
gitHubBuilder.withJwtToken(token);
} catch (Exception e) {
LOGGER.error("PEM Key or App Id is Invalid");
throw new FlowRegistryException(e.getMessage());
exceptionfactory marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Expand Down Expand Up @@ -392,41 +395,6 @@ public GHContent deleteContent(final String filePath, final String commitMessage
});
}

/**
* Creates the JwtToken for Authentication with Private Key
*
* @param pemString is the PKCS#1 String
* @return the JwtToken
*
* @throws Exception if an error occurs parsing key
*/
private static String loadPrivateKeyFromPEM(String pemString) throws Exception {
long nowMillis = System.currentTimeMillis();
long expMillis = nowMillis + 600000; // Token validity 10 minutes
Date now = new Date(nowMillis);
Date exp = new Date(expMillis);
PEMParser pemParser = new PEMParser(new StringReader(pemString));
Object object = pemParser.readObject();
pemParser.close();

if (object instanceof PEMKeyPair) {
PEMKeyPair keyPair = (PEMKeyPair) object;
RSAPrivateKey rsaPrivateKey = RSAPrivateKey.getInstance(keyPair.getPrivateKeyInfo().parsePrivateKey());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return (Jwts.builder().issuer(builder().appId)
.issuedAt(now)
.expiration(exp)
.signWith(privateKey,SignatureAlgorithm.RS256)
.compact());
} else {
LOGGER.error("Not a valid PKCS#1 PEM string");
}
LOGGER.warn("INVALID PEM KEY");
return "";
}

private String getResolvedPath(final String path) {
return repoPath == null ? path : repoPath + "/" + path;
}
Expand Down