From ac73e0fe9fee8431ad69d89c629386334af24b69 Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Fri, 24 Aug 2018 11:22:58 -0600 Subject: [PATCH 1/6] Authentication using Kubernetes Authentication This code was contributed by a customer. It provides support for loading the token provided by the authn-k8s authenticator. --- src/main/java/net/conjur/api/Conjur.java | 5 ++++ src/main/java/net/conjur/api/Variables.java | 4 +++ .../conjur/api/clients/AuthnK8sClient.java | 21 +++++++++++++++ .../conjur/api/clients/ResourceClient.java | 26 +++++++++++++++---- 4 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 src/main/java/net/conjur/api/clients/AuthnK8sClient.java diff --git a/src/main/java/net/conjur/api/Conjur.java b/src/main/java/net/conjur/api/Conjur.java index 7d0450f..e7e2d3b 100644 --- a/src/main/java/net/conjur/api/Conjur.java +++ b/src/main/java/net/conjur/api/Conjur.java @@ -31,6 +31,11 @@ public Conjur(Credentials credentials) { variables = new Variables(credentials); } + + public Conjur(Token token) { + variables = new Variables(token); + } + /** * Get a Variables instance configured with the same parameters as this instance. * @return the variables instance diff --git a/src/main/java/net/conjur/api/Variables.java b/src/main/java/net/conjur/api/Variables.java index c04c709..14228bf 100644 --- a/src/main/java/net/conjur/api/Variables.java +++ b/src/main/java/net/conjur/api/Variables.java @@ -11,6 +11,10 @@ public Variables(Credentials credentials) { credentials.getUsername(), credentials.getPassword(), Endpoints.fromSystemProperties()); } + public Variables(Token token) { + resourceClient = new ResourceClient(token, Endpoints.fromSystemProperties()); + } + public String retrieveSecret(String variableId) { return resourceClient.retrieveSecret(variableId); } diff --git a/src/main/java/net/conjur/api/clients/AuthnK8sClient.java b/src/main/java/net/conjur/api/clients/AuthnK8sClient.java new file mode 100644 index 0000000..d549607 --- /dev/null +++ b/src/main/java/net/conjur/api/clients/AuthnK8sClient.java @@ -0,0 +1,21 @@ +package net.conjur.api.clients; +import net.conjur.api.AuthnProvider; +import net.conjur.api.Token; + +public class AuthnK8sClient implements AuthnProvider { + + private Token token; + + public AuthnK8sClient(Token token) { + this.token = token; + } + + public Token authenticate() { + return token; + } + + public Token authenticate(boolean useCachedToken) { + return this.authenticate(); + } + +} diff --git a/src/main/java/net/conjur/api/clients/ResourceClient.java b/src/main/java/net/conjur/api/clients/ResourceClient.java index 74babb9..bdc9986 100644 --- a/src/main/java/net/conjur/api/clients/ResourceClient.java +++ b/src/main/java/net/conjur/api/clients/ResourceClient.java @@ -1,10 +1,5 @@ package net.conjur.api.clients; -import net.conjur.api.Endpoints; -import net.conjur.api.ResourceProvider; -import net.conjur.util.EncodeUriComponent; -import net.conjur.util.rs.TokenAuthFilter; - import javax.ws.rs.WebApplicationException; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; @@ -12,6 +7,12 @@ import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.Response; +import net.conjur.api.Endpoints; +import net.conjur.api.ResourceProvider; +import net.conjur.api.Token; +import net.conjur.util.EncodeUriComponent; +import net.conjur.util.rs.TokenAuthFilter; + /** * Conjur service client. */ @@ -26,6 +27,13 @@ public ResourceClient(final String username, final String password, final Endpoi init(username, password); } + // Build ResourceClient using a K8S auth token + public ResourceClient(final Token token, final Endpoints endpoints) { + this.endpoints = endpoints; + + init(token); + } + public String retrieveSecret(String variableId) { Response response = secrets.path(variableId).request().get(Response.class); validateResponse(response); @@ -51,6 +59,14 @@ private void init(String username, String password){ secrets = client.target(getEndpoints().getSecretsUri()); } + private void init(Token token){ + final ClientBuilder builder = ClientBuilder.newBuilder() + .register(new TokenAuthFilter(new AuthnK8sClient(token))); + + Client client = builder.build(); + + secrets = client.target(getEndpoints().getSecretsUri()); + } // TODO orenbm: Remove when we have a response filter to handle this private void validateResponse(Response response) { int status = response.getStatus(); From 98651dccaec4bd90ca2f6ecfe0b27a8ad4737df4 Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Fri, 24 Aug 2018 13:16:15 -0600 Subject: [PATCH 2/6] Added documentation This commit includes an updated README and JavaDocs --- README.md | 45 ++++++++++++++++++------ src/main/java/net/conjur/api/Conjur.java | 8 +++-- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c397508..52ddd36 100644 --- a/README.md +++ b/README.md @@ -29,13 +29,13 @@ If you are using Maven to manage your project's dependencies, you can run `mvn i If you aren't using Maven, you can add the `jar` in the normal way. This `jar` can be found in the `target` directory created when you ran `mvn package`. -Note that we ran `mvn package` without running the integration tests, since these require access to a Conjur instance. You can run the +Note that we ran `mvn package` without running the integration tests, since these require access to a Conjur instance. You can run the integration tests with `mvn package` once you finished with the configuration. ### Configuration -The simplest way to configure the Conjur API is by using environment variables, which is often a bit more convenient. -Environment variables are mapped to configuration variables by prepending `CONJUR_` to the all-caps name of the +The simplest way to configure the Conjur API is by using environment variables, which is often a bit more convenient. +Environment variables are mapped to configuration variables by prepending `CONJUR_` to the all-caps name of the configuration variable. For example, `appliance_url` is `CONJUR_APPLIANCE_URL`, `account` is `CONJUR_ACCOUNT` etc. The following environment variables are mandatory for running the API: CONJUR_ACCOUNT, CONJUR_AUTHN_LOGIN, CONJUR_AUTHN_API_KEY & CONJUR_APPLIANCE_URL. @@ -96,20 +96,49 @@ to your keystore like this: keytool -import -alias conjur-youraccount -keystore "$JRE_HOME/lib/security/cacerts" -file ./conjur-youraccount.der ``` -## Basic Usage +## Examples -### Creating a Conjur Instance +### Authorization Patterns +All authorization options require the environment variables `CONJUR_ACCOUNT` and `CONJUR_APPLIANCE_URL` are set: +```sh +export CONJUR_ACCOUNT= +export CONJUR_APPLIANCE_URL= +``` A `Conjur` instance provides access to the individual Conjur services. To create one, you'll need the environment variables as described above. You will typically create a Conjur instance from these values in the following way: +#### Environment Variables +```sh +# Additionally set the following environment variables: +export CONJUR_AUTHN_LOGIN= +export CONJUR_AUTHN_API_KEY= +``` ```java +// Using environment variables Conjur conjur = new Conjur(); +``` +#### Username and Password +```java +// Authenticate using provided username/hostname and password/API key +Conjur conjur = new Conjur('host/host-id', 'api-key'); +Conjur conjur = new Conjur('username', 'password'); ``` -where the Conjur object is logged in to the account & ready for use. +#### Credentials +```java +// Authenticate using a Credentials object +Credentials credentials = new Credentials('username', 'password'); +Conjur conjur = new Conjur(credentials); +``` +#### Authorization Token +```java +String authTokenString = new String(Files.readAllBytes(Paths.get('path/to/conjur/authentication/token.json'))); +Token token = Token.fromJson(authTokenString); +Conjur conjur = new Conjur(token); +``` ### Variable Operations @@ -119,14 +148,10 @@ A variable can have one or more (up to 20) secrets associated with it, and order You will typically add secrets to variables & retrieve secrets from variables in the following way: ```java -Conjur conjur = new Conjur(); - conjur.variables().addSecret(VARIABLE_KEY, VARIABLE_VALUE); - String retrievedSecret = conjur.variables().retrieveSecret(VARIABLE_KEY); ``` - ## JAX-RS Implementations The Conjur API client uses the JAX-RS standard to make requests to the Conjur web services. In the future we plan to diff --git a/src/main/java/net/conjur/api/Conjur.java b/src/main/java/net/conjur/api/Conjur.java index e7e2d3b..fca9f47 100644 --- a/src/main/java/net/conjur/api/Conjur.java +++ b/src/main/java/net/conjur/api/Conjur.java @@ -31,11 +31,15 @@ public Conjur(Credentials credentials) { variables = new Variables(credentials); } - + + /** + * Create a Conjur instance that uses a ResourceClient & an AuthnClient constructed with the given credentials + * @param token the conjur authorization token to use + */ public Conjur(Token token) { variables = new Variables(token); } - + /** * Get a Variables instance configured with the same parameters as this instance. * @return the variables instance From b3b2146b3057d9819f6fb1d370e1b080fc7602a6 Mon Sep 17 00:00:00 2001 From: Jason Vanderhoof Date: Fri, 24 Aug 2018 13:24:29 -0600 Subject: [PATCH 3/6] Bump version and update Changelog This commit includes a minor level version change as well as a Changelog entry. --- CHANGELOG.md | 6 +++++- README.md | 2 +- pom.xml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ed0c8d..4605e42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +## [2.1.0] - 2018-08-24 +### Added +- Adds support for token based authentication to support Kubernetes Authenticator + ## [2.0.0](https://github.com/cyberark/conjur-api-java/releases/tag/v2.0.0) - 2018-07-12 ### Added - License updated to Apache v2 - [PR #8](https://github.com/cyberark/conjur-api-java/pull/8) @@ -21,7 +25,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [1.3.0] - 2015-04-16 ### Changed -- Change variable behavior to reflect the fact that you may not have 'read' permission on +- Change variable behavior to reflect the fact that you may not have 'read' permission on a variable that you can 'execute' or 'update'. - Allow SSL hostname verification to be disabled in order to facilitate development and debugging. diff --git a/README.md b/README.md index 52ddd36..23d7417 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ If you are using Maven to manage your project's dependencies, you can run `mvn i net.conjur.api conjur-api - 2.0.0 + 2.1.0 ``` diff --git a/pom.xml b/pom.xml index 8c43c6b..d4c08f1 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ net.conjur.api conjur-api - 2.0.0 + 2.1.0 Conjur Client for the Conjur API From abc882030bd8bcd248048b31e3d8bf85a847ad28 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Dec 2018 09:59:08 -0500 Subject: [PATCH 4/6] Rename classes to represent more generic access token. --- .../clients/{AuthnK8sClient.java => AuthnTokenClient.java} | 4 ++-- src/main/java/net/conjur/api/clients/ResourceClient.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/main/java/net/conjur/api/clients/{AuthnK8sClient.java => AuthnTokenClient.java} (75%) diff --git a/src/main/java/net/conjur/api/clients/AuthnK8sClient.java b/src/main/java/net/conjur/api/clients/AuthnTokenClient.java similarity index 75% rename from src/main/java/net/conjur/api/clients/AuthnK8sClient.java rename to src/main/java/net/conjur/api/clients/AuthnTokenClient.java index d549607..1de01c3 100644 --- a/src/main/java/net/conjur/api/clients/AuthnK8sClient.java +++ b/src/main/java/net/conjur/api/clients/AuthnTokenClient.java @@ -2,11 +2,11 @@ import net.conjur.api.AuthnProvider; import net.conjur.api.Token; -public class AuthnK8sClient implements AuthnProvider { +public class AuthnTokenClient implements AuthnProvider { private Token token; - public AuthnK8sClient(Token token) { + public AuthnTokenClient(Token token) { this.token = token; } diff --git a/src/main/java/net/conjur/api/clients/ResourceClient.java b/src/main/java/net/conjur/api/clients/ResourceClient.java index bdc9986..e1d32fd 100644 --- a/src/main/java/net/conjur/api/clients/ResourceClient.java +++ b/src/main/java/net/conjur/api/clients/ResourceClient.java @@ -27,7 +27,7 @@ public ResourceClient(final String username, final String password, final Endpoi init(username, password); } - // Build ResourceClient using a K8S auth token + // Build ResourceClient using a Conjur auth token public ResourceClient(final Token token, final Endpoints endpoints) { this.endpoints = endpoints; @@ -61,7 +61,7 @@ private void init(String username, String password){ private void init(Token token){ final ClientBuilder builder = ClientBuilder.newBuilder() - .register(new TokenAuthFilter(new AuthnK8sClient(token))); + .register(new TokenAuthFilter(new AuthnTokenClient(token))); Client client = builder.build(); From aed8032fc5423cff4bd21e40c66d877b5982eb30 Mon Sep 17 00:00:00 2001 From: Micah Lee Date: Fri, 21 Dec 2018 10:02:04 -0500 Subject: [PATCH 5/6] Add support for loading token by filepath or environment var --- README.md | 12 ++++++++-- src/main/java/net/conjur/api/Token.java | 30 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 23d7417..059d6d3 100644 --- a/README.md +++ b/README.md @@ -135,8 +135,16 @@ Conjur conjur = new Conjur(credentials); #### Authorization Token ```java -String authTokenString = new String(Files.readAllBytes(Paths.get('path/to/conjur/authentication/token.json'))); -Token token = Token.fromJson(authTokenString); +Token token = Token.fromFile(Paths.get('path/to/conjur/authentication/token.json')); +Conjur conjur = new Conjur(token); +``` + +Alternatively, to use the `CONJUR_AUTHN_TOKEN_FILE` environment variable: +```bash +export CONJUR_AUTHN_TOKEN_FILE="path/to/conjur/authentication/token.json" +``` +```java +Token token = Token.fromEnv(); Conjur conjur = new Conjur(token); ``` diff --git a/src/main/java/net/conjur/api/Token.java b/src/main/java/net/conjur/api/Token.java index 29cf886..9f3d4b7 100644 --- a/src/main/java/net/conjur/api/Token.java +++ b/src/main/java/net/conjur/api/Token.java @@ -8,6 +8,12 @@ import org.joda.time.format.DateTimeFormatter; import java.nio.charset.StandardCharsets; +import java.nio.charset.Charset; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; /** * Represents a Conjur API authentication token. @@ -17,6 +23,7 @@ public class Token { private static final DateTimeFormatter DATE_TIME_FORMATTER = // tokens use dates like 2013-10-01 18:48:32 UTC DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss ZZZ"); + private static final String TOKEN_FILE_ENV_VARIABLE = "CONJUR_AUTHN_TOKEN_FILE"; // Hold our fields in here to facilitate json serialization/deserialization private static class Fields { @@ -123,6 +130,29 @@ public static Token fromJson(String json){ return new Token(json); } + public static Token fromFile(Path filepath, Charset encoding) + throws IOException { + byte[] encodedJson = Files.readAllBytes(filepath); + String json = new String(encodedJson, encoding); + return fromJson(json); + } + + public static Token fromFile(Path filepath) + throws IOException { + return fromFile(filepath, StandardCharsets.UTF_8); + } + + public static Token fromEnv(Charset encoding) + throws IOException { + String tokenFilePath = System.getenv(TOKEN_FILE_ENV_VARIABLE); + return fromFile(Paths.get(tokenFilePath), encoding); + } + + public static Token fromEnv() + throws IOException { + return fromEnv(StandardCharsets.UTF_8); + } + private String fromBase64(String base64){ return new String(Base64.decodeBase64(base64), StandardCharsets.UTF_8); } From 9d081f3e402cee21aa4e729416e53d0b985d449a Mon Sep 17 00:00:00 2001 From: Rafi Schwarz Date: Wed, 2 Jan 2019 09:11:03 -0500 Subject: [PATCH 6/6] Update README.md Co-Authored-By: micahlee --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 059d6d3..c7092ab 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ keytool -import -alias conjur-youraccount -keystore "$JRE_HOME/lib/security/cace ## Examples ### Authorization Patterns -All authorization options require the environment variables `CONJUR_ACCOUNT` and `CONJUR_APPLIANCE_URL` are set: +All authorization options require the environment variables `CONJUR_ACCOUNT` and `CONJUR_APPLIANCE_URL` to be set: ```sh export CONJUR_ACCOUNT= export CONJUR_APPLIANCE_URL=