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

Adds support for token based authentication #23

Merged
merged 6 commits into from
Jan 2, 2019
Merged
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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.

Expand Down
55 changes: 44 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,20 @@ If you are using Maven to manage your project's dependencies, you can run `mvn i
<dependency>
<groupId>net.conjur.api</groupId>
<artifactId>conjur-api</artifactId>
<version>2.0.0</version>
<version>2.1.0</version>
</dependency>
```

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.
Expand Down Expand Up @@ -96,20 +96,57 @@ 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` to be set:
```sh
export CONJUR_ACCOUNT=<account specified during Conjur setup>
export CONJUR_APPLIANCE_URL=<Conjur HTTPS endpoint>
```

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=<user/host identity>
export CONJUR_AUTHN_API_KEY=<user/host 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
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);
```

### Variable Operations

Expand All @@ -119,14 +156,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
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>net.conjur.api</groupId>
<artifactId>conjur-api</artifactId>
<version>2.0.0</version>
<version>2.1.0</version>

<name>Conjur</name>
<description>Client for the Conjur API</description>
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/net/conjur/api/Conjur.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ public Conjur(Credentials credentials) {
variables = new Variables(credentials);
}


/**
* Create a Conjur instance that uses a ResourceClient &amp; 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
Expand Down
30 changes: 30 additions & 0 deletions src/main/java/net/conjur/api/Token.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 {
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/net/conjur/api/Variables.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/net/conjur/api/clients/AuthnTokenClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package net.conjur.api.clients;
import net.conjur.api.AuthnProvider;
import net.conjur.api.Token;

public class AuthnTokenClient implements AuthnProvider {

private Token token;

public AuthnTokenClient(Token token) {
this.token = token;
}

public Token authenticate() {
return token;
}

public Token authenticate(boolean useCachedToken) {
return this.authenticate();
}

}
26 changes: 21 additions & 5 deletions src/main/java/net/conjur/api/clients/ResourceClient.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
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;
import javax.ws.rs.client.Entity;
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.
*/
Expand All @@ -26,6 +27,13 @@ public ResourceClient(final String username, final String password, final Endpoi
init(username, password);
}

// Build ResourceClient using a Conjur 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);
Expand All @@ -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 AuthnTokenClient(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();
Expand Down