quarkiverse / quarkus-github-app

Develop your GitHub Apps in Java with Quarkus.
https://docs.quarkiverse.io/quarkus-github-app/dev/index.html
Apache License 2.0
60 stars 27 forks source link

CredentialsProvider for GitHub Private Key #600

Closed gilday closed 3 months ago

gilday commented 3 months ago

Would it be appropriate to modify the configuration for this extension to optionally make use of a Quarkus CredentialsProvider such that the GitHub Private Key may be provided this way?

Here's a specific use case: I want to deploy a Quarkus GitHub App on AWS Lambda and managed the GitHub private key in AWS Secrets Manager. Short of extending Lambda to set environment variables on start-up using a wrapper script, there's no way to make the key in Secrets Manager available to the Quarkus configuration system. I understand the Quarkus CredentialsManager exists to bridge such a gap.

gsmet commented 3 months ago

That's a very good idea. I experimented with it there: https://github.com/quarkiverse/quarkus-github-app/pull/601

Let me know if it works for you.

gsmet commented 3 months ago

And if you end up getting it to work as a lambda, I'm interested in your feedback and maybe we could include some tips and tricks in the documentation.

Speaking of documentation, once we agree on the implementation, I will add some.

ryandens commented 3 months ago

👋 Hi @gsmet, I'm working with @gilday on this one, thank you for responding so quickly! I think this would work out quite well for us! I prototyped the CredentialProvider I would imagine us implementing to validate this would work for us and figured it was worth sharing.

import io.quarkus.arc.Unremovable;
import io.quarkus.credentials.CredentialsProvider;
import io.quarkiverse.githubapp.Credentials;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import java.util.Map;
import java.util.Objects;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;

/**
 * A {@link CredentialsProvider} implementation that retrieves GitHub App credentials from AWS
 * Secrets Manager and provides them to the Quarkus GitHub App extension
 */
@ApplicationScoped
@Unremovable
@Named("github-app-credentials-provider")
public class GitHubAppCredentialsProvider implements CredentialsProvider {

  private final String githubAppCredentialsProviderName;
  private final String privateKeySecretName;
  private final String webhookSecretName;
  private final SecretsManagerClient secrets;

  @Inject
  public GitHubAppCredentialsProvider(
      @ConfigProperty(name = "quarkus.github-app.credentials-provider-name")
          final String githubAppCredentialsProviderName,
      @ConfigProperty(name = "com.example.github-app.private-key-secret-name")
          final String privateKeySecretName,
      @ConfigProperty(name = "com.example.github-app.webhook-secret-name")
          final String webhookSecretName,
      final SecretsManagerClient secrets) {
    this.githubAppCredentialsProviderName =
        Objects.requireNonNull(githubAppCredentialsProviderName);
    this.privateKeySecretName = Objects.requireNonNull(privateKeySecretName);
    this.webhookSecretName = Objects.requireNonNull(webhookSecretName);
    this.secrets = Objects.requireNonNull(secrets);
  }

  @Override
  public Map<String, String> getCredentials(String credentialsProviderName) {
    if (githubAppCredentialsProviderName.equals(credentialsProviderName)) {
      final var privateKey =
          secrets.getSecretValue(builder -> builder.secretId(privateKeySecretName)).secretString();
      final var webhookSecret =
          secrets.getSecretValue(builder -> builder.secretId(webhookSecretName)).secretString();
      return Map.of(Credentials.PRIVATE_KEY, privateKey, Credentials.WEBHOOK_SECRET, webhookSecret);
    }
    return Map.of();
  }
}

We would then configure the Quarkus GitHub App configuration properties:

quarkus.github-app.credentials-provider-name=custom
quarkus.github-app.credentials-provider-name=github-app-credentials-provider
com.example.github-app.private-key-secret-name=secret-key-name
com.example.github-app.webhook-secret-name=webhook-secret-name
gsmet commented 3 months ago

I added some doc and a test and merged the PR.

Unfortunately, I wasn't able to release 2.5.0 yet as the Sonatype server we use to release our jars is under maintenance. I'll publish a new release ASAP.

gsmet commented 2 months ago

2.5.1 is now available on Maven Central with this new feature.