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

Making the path of conjur.properties configurable #105

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,16 @@ nginx.key
api_key
.settings/
**/.settings/

######################
# Intellij
######################
.idea/
*.iml
*.iws
*.ipr
*.ids
*.orig
classes/
out/
.DS_Store
27 changes: 14 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,18 +310,18 @@ You can do this by setting Conjur Properties or [Environment variables](#environ
#### CyberArk Conjur Configuration Properties
The following configuration properties can be set in the standard `spring-boot` configuration files, `application.properties` or `application.yml`:

| Parameter name | Description |
|:-------------------------|:----------------------------------------|
| conjur.account | CyberArk Conjur Account |
| conjur.appliance-url | CyberArk Conjur Appliance URL |
| conjur.authn-login | CyberArk Conjur User /host identity |
| conjur.authn-api-key | CyberArk Conjur API KEY of the host |
| conjur.auth-token-file | CyberArk Conjur Token, stored in a file |
| conjur.cert-file | CyberArk Conjur SSL Certificate path |
| conjur.ssl-certificate | CyberArk Conjur SSL Certificate Content |
| conjur.authenticator-id | CyberArk Conjur authenticator ID |
| conjur.jwt-token-path | CyberArk Conjur Path of the JWT Token |

| Parameter name | Description |
|:------------------------|:----------------------------------------|
| conjur.account | CyberArk Conjur Account |
| conjur.appliance-url | CyberArk Conjur Appliance URL |
| conjur.authn-login | CyberArk Conjur User /host identity |
| conjur.authn-api-key | CyberArk Conjur API KEY of the host |
| conjur.auth-token-file | CyberArk Conjur Token, stored in a file |
| conjur.cert-file | CyberArk Conjur SSL Certificate path |
| conjur.ssl-certificate | CyberArk Conjur SSL Certificate Content |
| conjur.authenticator-id | CyberArk Conjur authenticator ID |
| conjur.jwt-token-path | CyberArk Conjur Path of the JWT Token |
| conjur.mapping-path | CyberArk Conjur Mapping Path |

<h4 id="environment-variables">
Environment Variables
Expand All @@ -334,7 +334,7 @@ For example:`appliance_url` is `CONJUR_APPLIANCE_URL`, `account` is `CONJUR_ACCO
If no other configuration is done (e.g. over system properties or CLI parameters), include the following environment variables in the app's runtime environment to use the Spring Boot Plugin.

| Name | Environment ID | Description | API KEY | JWT |
| ----------------------- | ----------------------- | -------------------------- | ------- | ---- |
|-------------------------|-------------------------|----------------------------| ------- | ---- |
| Conjur Account | CONJUR_ACCOUNT | Account to connect | Yes | Yes |
| API key | CONJUR_AUTHN_API_KEY | User/host API Key/password | Yes | No |
| Connection url | CONJUR_APPLIANCE_URL | Conjur instance to connect | Yes | Yes |
Expand All @@ -343,6 +343,7 @@ If no other configuration is done (e.g. over system properties or CLI parameters
| SSL Certificate Content | CONJUR_SSL_CERTIFICATE | Certificate content | Yes | Yes |
| Path of the JWT Token | CONJUR_JWT_TOKEN_PATH | Path of the JWT Token | No | Yes |
| Conjur authenticator ID | CONJUR_AUTHENTICATOR_ID | Conjur authenticator ID | No | Yes |
| Conjur MAPPING PATH | CONJUR_MAPPING_PATH | Conjur Mapping PATH | Yes | Yes |

Only one CONJUR_CERT_FILE and CONJUR_SSL_CERTIFICATE is required. There are two variables to allow the user to specify the path to a certificate file or provide the certificate data directly in an environment variable.
</details>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.LinkedHashMap;

import com.cyberark.conjur.sdk.endpoint.SecretsApi;
import com.cyberark.conjur.springboot.core.env.ConjurConfig;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
Expand Down Expand Up @@ -58,6 +59,7 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
continue;
}
ps.setSecretsApi(beanFactory.getBean(SecretsApi.class));
ps.setConjurConfig(beanFactory.getBean(ConjurConfig.class));
propertySources.addLast(ps);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,63 +1,97 @@
package com.cyberark.conjur.springboot.core.env;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Properties;

import com.cyberark.conjur.springboot.constant.ConjurConstant;
import com.cyberark.conjur.springboot.domain.ConjurProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.util.ResourceUtils;

import static com.cyberark.conjur.springboot.constant.ConjurConstant.CONJUR_PREFIX;

/**
*
* This class loads the external configured conjur.properties file and resolves
* the keys values defined in properties file.
*
*/
public class ConjurConfig {
public class ConjurConfig implements EnvironmentAware, BeanFactoryPostProcessor {

private static final Properties PROPS = new Properties();

private static final ConjurConfig UNIQUE_INSTANCE = new ConjurConfig();

private static final Logger LOGGER = LoggerFactory.getLogger(ConjurConfig.class);
/**
* The Environment.
*/
private Environment environment;

private ConjurConfig() {
/**
*
* @param name - key define at given property file.
* @return - corresponding value of key defined at given property file.
*/
public String mapProperty(String name) {
String mapped = PROPS.getProperty(ConjurConstant.CONJUR_MAPPING + name);
return mapped != null ? mapped : name;
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
final BindResult<ConjurProperties> result = Binder.get(environment).bind(CONJUR_PREFIX, ConjurProperties.class);
if (result.isBound()) {
loadMappingProps(result);
}
}

InputStream propsFile = ConjurConfig.class.getResourceAsStream(ConjurConstant.CONJUR_PROPERTIES);
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}

private void loadMappingProps(BindResult<ConjurProperties> result) {
String mappingPath = result.get().getMappingPath();
InputStream propsFile = null;
if (mappingPath != null) {
try {
File file = ResourceUtils.getFile(mappingPath);
propsFile = Files.newInputStream(file.toPath());
}
catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
}
else {
propsFile = ConjurConfig.class.getResourceAsStream(ConjurConstant.CONJUR_PROPERTIES);
}

if (propsFile != null) {
try {
PROPS.load(propsFile);
} catch (IOException e) {
}
catch (IOException e) {
LOGGER.error(e.getMessage(), e);
} finally {
}
finally {
try {
propsFile.close();
} catch (IOException e) {
}
catch (IOException e) {
LOGGER.error(e.getMessage(), e);
}
}
}

}

/**
*
* @return unique instance of class.
*/
public static ConjurConfig getInstance() {
return UNIQUE_INSTANCE;
}

/**
*
* @param name - key define at given property file.
* @return - corresponding value of key defined at given property file.
*/
public String mapProperty(String name) {
String mapped = PROPS.getProperty(ConjurConstant.CONJUR_MAPPING + name);

return mapped != null ? mapped : name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class ConjurPropertySource extends EnumerablePropertySource<Object> {
private SecretsApi secretsApi;

private List<String> properties;

private ConjurConfig conjurConfig;

private static final Logger LOGGER = LoggerFactory.getLogger(ConjurPropertySource.class);

Expand Down Expand Up @@ -73,7 +75,7 @@ public Object getProperty(String key) {
this.vaultPath = vaultPath.concat("/");
}
if (propertyExists(key)) {
key = ConjurConfig.getInstance().mapProperty(key);
key = conjurConfig.mapProperty(key);
try {
String account = ConjurConnectionManager.getAccount(secretsApi);
String secretValue = secretsApi.getSecret(account, ConjurConstant.CONJUR_KIND, vaultPath + key);
Expand All @@ -98,4 +100,8 @@ public void setSecretsApi(SecretsApi secretsApi) {
private boolean propertyExists(String key) {
return properties.stream().anyMatch(property -> property.contains(key));
}

public void setConjurConfig(ConjurConfig conjurConfig) {
this.conjurConfig = conjurConfig;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ public class ConjurProperties{
*/
private String authenticatorId;

/**
* The Conjur mapping path.
*/
private String mappingPath;

/**
* Gets account.
*
Expand Down Expand Up @@ -218,6 +223,24 @@ public void setAuthenticatorId(String authenticatorId) {
this.authenticatorId = authenticatorId;
}

/**
* Gets conjur mapping path.
*
* @return the conjur mapping path
*/
public String getMappingPath() {
return mappingPath;
}

/**
* Sets conjur mapping path.
*
* @param mappingPath the conjur mapping path
*/
public void setMappingPath(String mappingPath) {
this.mappingPath = mappingPath;
}

@Override
public String toString() {
return "ConjurProperties{" +
Expand All @@ -230,6 +253,7 @@ public String toString() {
", sslCertificate='" + sslCertificate + '\'' +
", jwtTokenPath='" + jwtTokenPath + '\'' +
", authenticatorId='" + authenticatorId + '\'' +
", conjurMappingPath='" + mappingPath + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.springframework.core.env.Environment;

import com.cyberark.conjur.sdk.endpoint.SecretsApi;
import com.cyberark.conjur.springboot.core.env.ConjurConfig;
import com.cyberark.conjur.springboot.service.CustomPropertySourceChain;
import com.cyberark.conjur.springboot.service.DefaultPropertySourceChain;
import com.cyberark.conjur.springboot.service.PropertyProcessorChain;
Expand All @@ -31,14 +32,17 @@ public class ConjurCloudProcessor implements BeanPostProcessor, InitializingBean

private PropertyProcessorChain processorChain;

private ConjurConfig conjurConfig;

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}

public ConjurCloudProcessor(SecretsApi secretsApi) {
public ConjurCloudProcessor(SecretsApi secretsApi, ConjurConfig conjurConfig) {
super();
this.secretsApi = secretsApi;
this.conjurConfig= conjurConfig;
}

@Override
Expand All @@ -48,6 +52,7 @@ public void afterPropertiesSet() throws Exception {
CustomPropertySourceChain customPS = new CustomPropertySourceChain("CustomPropertySource");
processorChain.setNextChain(customPS);
customPS.setSecretsApi(secretsApi);
customPS.setConjurConfig(conjurConfig);
environment.getPropertySources().addLast(processorChain);

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

import static com.cyberark.conjur.springboot.constant.ConjurConstant.CONJUR_PREFIX;

import com.cyberark.conjur.springboot.core.env.ConjurConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
Expand Down Expand Up @@ -61,11 +62,16 @@ ConjurProperties conjurProperties(){

@ConditionalOnMissingBean(ConjurPropertySource.class)
@Bean
static ConjurCloudProcessor conjurCloudProcessor(SecretsApi secretsApi) {
static ConjurCloudProcessor conjurCloudProcessor(SecretsApi secretsApi, ConjurConfig conjurConfig) {

LOGGER.info("Creating ConjurCloudProcessor instance");

return new ConjurCloudProcessor(secretsApi);
return new ConjurCloudProcessor(secretsApi, conjurConfig);
}

@ConditionalOnMissingBean
@Bean
static ConjurConfig conjurConfig() {
return new ConjurConfig();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class CustomPropertySourceChain extends PropertyProcessorChain {

private SecretsApi secretsApi;

private ConjurConfig conjurConfig;

public CustomPropertySourceChain(String name) {
super("customPropertySource");

Expand All @@ -41,6 +43,10 @@ public void setSecretsApi(SecretsApi secretsApi) {
this.secretsApi = secretsApi;
}

public void setConjurConfig(ConjurConfig conjurConfig) {
this.conjurConfig = conjurConfig;
}

@Override
public String[] getPropertyNames() {

Expand All @@ -52,7 +58,7 @@ public Object getProperty(String key) {

byte[] result = null;

key = ConjurConfig.getInstance().mapProperty(key);
key = conjurConfig.mapProperty(key);

if (!(key.startsWith(ConjurConstant.SPRING_VAR)) && !(key.startsWith(ConjurConstant.SERVER_VAR))
&& !(key.startsWith(ConjurConstant.ERROR)) && !(key.startsWith(ConjurConstant.SPRING_UTIL))
Expand Down
Loading