Skip to content
Open
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
55 changes: 55 additions & 0 deletions src/main/java/com/cyberark/conjur/api/Conjur.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.cyberark.conjur.api;

import javax.net.ssl.SSLContext;
import java.util.List;
import java.util.Map;

/**
* Entry point for the Conjur API client.
Expand Down Expand Up @@ -105,4 +107,57 @@ public Conjur(Token token, SSLContext sslContext) {
public Variables variables() {
return variables;
}

/**
* Fetch multiple secret values in one invocation.
*
* @param variableIds the variable IDs to retrieve
* @return a map of variable ID to secret value
*/
public Map<String, String> retrieveBatchSecrets(String... variableIds) {
return variables.retrieveBatchSecrets(variableIds);
}

/**
* List all resources visible to the authenticated identity.
*
* @return list of all resources
*/
public List<ConjurResource> listResources() {
return variables.listResources();
}

/**
* List resources filtered by kind.
*
* @param kind the resource kind (e.g. "variable", "host")
* @return resources matching the given kind
*/
public List<ConjurResource> listResources(String kind) {
return variables.listResources(kind);
}

/**
* List resources with full query parameter control.
*
* @param kind resource kind filter (null for all kinds)
* @param search text search filter (null for no search)
* @param limit max results (null for server default)
* @param offset pagination offset (null for no offset)
* @return resources matching the query
*/
public List<ConjurResource> listResources(String kind, String search, Integer limit, Integer offset) {
return variables.listResources(kind, search, limit, offset);
}

/**
* Count resources visible to the authenticated identity.
*
* @param kind resource kind filter (null for all kinds)
* @param search text search filter (null for no search)
* @return the number of matching resources
*/
public int countResources(String kind, String search) {
return variables.countResources(kind, search);
}
}
119 changes: 119 additions & 0 deletions src/main/java/com/cyberark/conjur/api/ConjurResource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package com.cyberark.conjur.api;

import java.util.List;
import java.util.Map;

/**
* Represents a Conjur resource returned by the
* <a href="https://docs.cyberark.com/conjur-open-source/latest/en/content/developer/conjur_api_list_resources.htm">List Resources</a> API.
*
* <p>A resource has an {@code id} in the form {@code {account}:{kind}:{identifier}},
* along with metadata such as owner, policy, creation time, permissions, and annotations.</p>
*/
public class ConjurResource {

private String created_at;
private String id;
private String owner;
private String policy;
private List<Permission> permissions;
private List<Annotation> annotations;
private List<Map<String, Object>> secrets;
private List<Map<String, Object>> policy_versions;

/** @return the creation timestamp */
public String getCreatedAt() { return created_at; }

/**
* The fully-qualified resource ID: {@code {account}:{kind}:{identifier}}
* @return the resource ID
*/
public String getId() { return id; }

/** @return the owner resource ID */
public String getOwner() { return owner; }

/** @return the policy resource ID this resource belongs to */
public String getPolicy() { return policy; }

/** @return the list of permissions on this resource */
public List<Permission> getPermissions() { return permissions; }

/** @return the list of annotations on this resource */
public List<Annotation> getAnnotations() { return annotations; }

/** @return secret version info (only for variables) */
public List<Map<String, Object>> getSecrets() { return secrets; }

/** @return policy version info (only for policies) */
public List<Map<String, Object>> getPolicyVersions() { return policy_versions; }

/**
* Extract the resource kind from the fully-qualified ID.
* For {@code myorg:variable:db/password}, returns {@code variable}.
*
* @return the kind portion of the ID, or null if the ID is malformed
*/
public String getKind() {
if (id == null) return null;
int first = id.indexOf(':');
int second = id.indexOf(':', first + 1);
if (first < 0 || second < 0) return null;
return id.substring(first + 1, second);
}

/**
* Extract the identifier (without account and kind prefix) from the fully-qualified ID.
* For {@code myorg:variable:db/password}, returns {@code db/password}.
*
* @return the identifier portion of the ID, or null if the ID is malformed
*/
public String getIdentifier() {
if (id == null) return null;
int first = id.indexOf(':');
int second = id.indexOf(':', first + 1);
if (first < 0 || second < 0) return null;
return id.substring(second + 1);
}

@Override
public String toString() {
return "ConjurResource{id='" + id + "'}";
}

/**
* Represents a permission entry on a resource.
*/
public static class Permission {
private String privilege;
private String role;
private String policy;

public String getPrivilege() { return privilege; }
public String getRole() { return role; }
public String getPolicy() { return policy; }

@Override
public String toString() {
return "Permission{privilege='" + privilege + "', role='" + role + "'}";
}
}

/**
* Represents an annotation (key-value metadata) on a resource.
*/
public static class Annotation {
private String name;
private String value;
private String policy;

public String getName() { return name; }
public String getValue() { return value; }
public String getPolicy() { return policy; }

@Override
public String toString() {
return "Annotation{name='" + name + "', value='" + value + "'}";
}
}
}
107 changes: 78 additions & 29 deletions src/main/java/com/cyberark/conjur/api/Endpoints.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,61 +7,110 @@
import java.net.URI;

/**
* An <code>Endpoints</code> instance provides endpoint URIs for the various conjur services.
* An <code>Endpoints</code> instance provides endpoint URIs for the various Conjur services.
*
* <p>The canonical way to construct an {@code Endpoints} is from an appliance URL and account name.
* All service URIs are derived from these two values:</p>
* <ul>
* <li>Authentication: {@code {applianceUrl}/authn/{account}}</li>
* <li>Secrets (single): {@code {applianceUrl}/secrets/{account}/variable}</li>
* <li>Secrets (batch): {@code {applianceUrl}/secrets}</li>
* <li>Resources: {@code {applianceUrl}/resources/{account}}</li>
* </ul>
*
* <p>For non-standard authenticators (LDAP, OIDC, etc.), supply a custom authn URL.</p>
*/
public class Endpoints implements Serializable {

private static final long serialVersionUID = 1L;
private final String applianceUrl;
private final String account;
private final URI authnUri;
private final URI secretsUri;

public Endpoints(final URI authnUri, final URI secretsUri){
this.authnUri = Args.notNull(authnUri, "authnUri");
this.secretsUri = Args.notNull(secretsUri, "secretsUri");
/**
* Create Endpoints from appliance URL and account, using standard authentication.
*
* @param applianceUrl the base Conjur appliance URL (e.g. {@code https://conjur.example.com})
* @param account the Conjur account name (e.g. {@code conjur} for SaaS, or your org name)
*/
public Endpoints(String applianceUrl, String account) {
this(applianceUrl, account, applianceUrl + "/authn");
}

public Endpoints(String authnUri, String secretsUri){
this(URI.create(authnUri), URI.create(secretsUri));
/**
* Create Endpoints from appliance URL, account, and a custom authentication URL.
* Use this when authenticating via a non-standard authenticator (LDAP, OIDC, etc.).
*
* @param applianceUrl the base Conjur appliance URL
* @param account the Conjur account name
* @param authnUrl the authentication service base URL
* (e.g. {@code https://conjur.example.com/authn-ldap/my-service})
*/
public Endpoints(String applianceUrl, String account, String authnUrl) {
this.applianceUrl = Args.notNull(applianceUrl, "applianceUrl");
this.account = Args.notNull(account, "account");
this.authnUri = URI.create(String.format("%s/%s", authnUrl, account));
this.secretsUri = URI.create(String.format("%s/secrets/%s/variable", applianceUrl, account));
}

public URI getAuthnUri(){ return authnUri; }
public URI getAuthnUri() { return authnUri; }

public URI getSecretsUri() {
return secretsUri;
public URI getSecretsUri() { return secretsUri; }

public String getAccount() { return account; }

public String getApplianceUrl() { return applianceUrl; }

/**
* Returns the base URI for batch secret retrieval: {@code {applianceUrl}/secrets}
*
* @return the batch secrets URI
*/
public URI getBatchSecretsUri() {
return URI.create(applianceUrl + "/secrets");
}

/**
* Returns the URI for listing resources: {@code {applianceUrl}/resources/{account}}
*
* @return the resources URI
*/
public URI getResourcesUri() {
return URI.create(String.format("%s/resources/%s", applianceUrl, account));
}

public static Endpoints fromSystemProperties(){
/**
* Create Endpoints from system properties / environment variables.
* Reads {@code CONJUR_ACCOUNT}, {@code CONJUR_APPLIANCE_URL}, and optionally {@code CONJUR_AUTHN_URL}.
*/
public static Endpoints fromSystemProperties() {
String account = Properties.getMandatoryProperty(Constants.CONJUR_ACCOUNT_PROPERTY);
String applianceUrl = Properties.getMandatoryProperty(Constants.CONJUR_APPLIANCE_URL_PROPERTY);
String authnUrl = Properties.getMandatoryProperty(Constants.CONJUR_AUTHN_URL_PROPERTY, applianceUrl + "/authn");
String authnUrl = Properties.getMandatoryProperty(
Constants.CONJUR_AUTHN_URL_PROPERTY, applianceUrl + "/authn");

return new Endpoints(
getAuthnServiceUri(authnUrl, account),
getServiceUri("secrets", account, "variable")
);
return new Endpoints(applianceUrl, account, authnUrl);
}

public static Endpoints fromCredentials(Credentials credentials){
/**
* Create Endpoints using the authentication URL from the given credentials.
* Account and appliance URL are read from system properties / environment variables.
*/
public static Endpoints fromCredentials(Credentials credentials) {
String account = Properties.getMandatoryProperty(Constants.CONJUR_ACCOUNT_PROPERTY);
return new Endpoints(
getAuthnServiceUri(credentials.getAuthnUrl(), account),
getServiceUri("secrets", account, "variable")
);
}

private static URI getAuthnServiceUri(String authnUrl, String accountName) {
return URI.create(String.format("%s/%s", authnUrl, accountName));
}
String applianceUrl = Properties.getMandatoryProperty(Constants.CONJUR_APPLIANCE_URL_PROPERTY);

private static URI getServiceUri(String service, String accountName, String path){
return URI.create(String.format("%s/%s/%s/%s", Properties.getMandatoryProperty(Constants.CONJUR_APPLIANCE_URL_PROPERTY), service, accountName, path));
return new Endpoints(applianceUrl, account, credentials.getAuthnUrl());
}

@Override
public String toString() {
return "Endpoints{" +
"authnUri=" + authnUri +
"secretsUri=" + secretsUri +
"applianceUrl=" + applianceUrl +
", account=" + account +
", authnUri=" + authnUri +
", secretsUri=" + secretsUri +
'}';
}
}
59 changes: 59 additions & 0 deletions src/main/java/com/cyberark/conjur/api/ResourceProvider.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.cyberark.conjur.api;

import java.util.List;
import java.util.Map;

/**
* Provides methods for retrieving and setting Conjur resources
*/
Expand All @@ -19,4 +22,60 @@ public interface ResourceProvider {
*/
void addSecret(String variableId, String secret);

/**
* Fetch multiple secret values in one invocation.
* It's faster to fetch secrets in batches than to fetch them one at a time.
*
* @param variableIds the variable IDs to retrieve (without account prefix)
* @return a map of variable ID to secret value
* @see <a href="https://docs.cyberark.com/conjur-open-source/latest/en/content/developer/conjur_api_batch_retrieve.htm">Batch Secret Retrieval</a>
*/
default Map<String, String> retrieveBatchSecrets(String... variableIds) {
throw new UnsupportedOperationException("Batch secret retrieval not supported");
}

/**
* List resources visible to the authenticated identity.
*
* @return all resources
* @see <a href="https://docs.cyberark.com/conjur-open-source/latest/en/content/developer/conjur_api_list_resources.htm">List Resources</a>
*/
default List<ConjurResource> listResources() {
throw new UnsupportedOperationException("List resources not supported");
}

/**
* List resources filtered by kind.
*
* @param kind the resource kind to filter by (e.g. "variable", "host", "user", "group", "layer", "policy", "webservice")
* @return resources matching the given kind
*/
default List<ConjurResource> listResources(String kind) {
throw new UnsupportedOperationException("List resources not supported");
}

/**
* List resources with full query parameter control.
*
* @param kind resource kind filter (null for all kinds)
* @param search text search filter (null for no search)
* @param limit max results (null for server default)
* @param offset pagination offset (null for no offset)
* @return resources matching the query
*/
default List<ConjurResource> listResources(String kind, String search, Integer limit, Integer offset) {
throw new UnsupportedOperationException("List resources not supported");
}

/**
* Count resources visible to the authenticated identity.
*
* @param kind resource kind filter (null for all kinds)
* @param search text search filter (null for no search)
* @return the number of matching resources
*/
default int countResources(String kind, String search) {
throw new UnsupportedOperationException("Count resources not supported");
}

}
Loading