DATACOUCH-322 - Add RBAC username and password support
Motivation
----------
Couchbase server 5.0 allows role based access control and this allows
for users to be created and granted access to use bucket. Expose this
feature in SDC.
Changes
-------
1. Couchbase configurations allow for user name to be set. The user password
property is still retrieved from bucket password property.
2. CouchbaseFactoryBean has additional constructor for the username
property.
3. Couchbase bucket schema for xml configurations also includes username
property.
4. Integration tests have been restructured majorly to accomadate for
username
- Testcontainers are used to allow for container based testing.
- Container based testing is optional, it can be configured using
resources/server.properties
Results
-------
The RBAC change has been tested with pre 5.0 and 5.0+ versions using
containers. The tests pass.
Original pull request: #158.
This commit is contained in:
@@ -55,6 +55,13 @@ public abstract class AbstractCouchbaseConfiguration
|
||||
*/
|
||||
protected abstract String getBucketName();
|
||||
|
||||
/**
|
||||
* The user of the bucket. Override the method for users in Couchbase Server 5.0+.
|
||||
*
|
||||
* @return user name.
|
||||
*/
|
||||
protected String getUsername() { return getBucketName(); }
|
||||
|
||||
/**
|
||||
* The password of the bucket (can be an empty string).
|
||||
*
|
||||
@@ -115,7 +122,7 @@ public abstract class AbstractCouchbaseConfiguration
|
||||
@Override
|
||||
@Bean(name = BeanNames.COUCHBASE_CLUSTER_INFO)
|
||||
public ClusterInfo couchbaseClusterInfo() throws Exception {
|
||||
return couchbaseCluster().clusterManager(getBucketName(), getBucketPassword()).info();
|
||||
return couchbaseCluster().clusterManager(getUsername(), getBucketPassword()).info();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,6 +134,13 @@ public abstract class AbstractCouchbaseConfiguration
|
||||
@Bean(destroyMethod = "close", name = BeanNames.COUCHBASE_BUCKET)
|
||||
public Bucket couchbaseClient() throws Exception {
|
||||
//@Bean method can use another @Bean method in the same @Configuration by directly invoking it
|
||||
return couchbaseCluster().openBucket(getBucketName(), getBucketPassword());
|
||||
Cluster cluster = couchbaseCluster();
|
||||
|
||||
if(!getUsername().contentEquals(getBucketName())){
|
||||
cluster.authenticate(getUsername(), getBucketPassword());
|
||||
} else if (!getBucketPassword().isEmpty()) {
|
||||
return cluster.openBucket(getBucketName(), getBucketPassword());
|
||||
}
|
||||
return cluster.openBucket(getBucketName());
|
||||
}
|
||||
}
|
||||
@@ -54,9 +54,16 @@ public abstract class AbstractReactiveCouchbaseConfiguration
|
||||
protected abstract String getBucketName();
|
||||
|
||||
/**
|
||||
* The password of the bucket (can be an empty string).
|
||||
* The user of the bucket. Override the method for users in Couchbase Server 5.0+.
|
||||
*
|
||||
* @return the password of the bucket.
|
||||
* @return the user name.
|
||||
*/
|
||||
protected String getUsername() { return getBucketName(); }
|
||||
|
||||
/**
|
||||
* The password of the bucket/User of the bucket (can be an empty string).
|
||||
*
|
||||
* @return the password of the bucket/user.
|
||||
*/
|
||||
protected abstract String getBucketPassword();
|
||||
|
||||
@@ -113,7 +120,7 @@ public abstract class AbstractReactiveCouchbaseConfiguration
|
||||
@Override
|
||||
@Bean(name = BeanNames.COUCHBASE_CLUSTER_INFO)
|
||||
public ClusterInfo couchbaseClusterInfo() throws Exception {
|
||||
return couchbaseCluster().clusterManager(getBucketName(), getBucketPassword()).info();
|
||||
return couchbaseCluster().clusterManager(getUsername(), getBucketPassword()).info();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,6 +132,13 @@ public abstract class AbstractReactiveCouchbaseConfiguration
|
||||
@Bean(destroyMethod = "close", name = BeanNames.COUCHBASE_BUCKET)
|
||||
public Bucket couchbaseClient() throws Exception {
|
||||
//@Bean method can use another @Bean method in the same @Configuration by directly invoking it
|
||||
return couchbaseCluster().openBucket(getBucketName(), getBucketPassword());
|
||||
Cluster cluster = couchbaseCluster();
|
||||
|
||||
if(!getUsername().contentEquals(getBucketName())){
|
||||
cluster.authenticate(getUsername(), getBucketPassword());
|
||||
} else if (!getBucketPassword().isEmpty()) {
|
||||
return cluster.openBucket(getBucketName(), getBucketPassword());
|
||||
}
|
||||
return cluster.openBucket(getBucketName());
|
||||
}
|
||||
}
|
||||
@@ -30,27 +30,30 @@ import org.springframework.data.couchbase.core.CouchbaseExceptionTranslator;
|
||||
* {@link Cluster} reference.
|
||||
*
|
||||
* @author Simon Baslé
|
||||
* @author Subhashni Balakrishnan
|
||||
*/
|
||||
public class CouchbaseBucketFactoryBean extends AbstractFactoryBean<Bucket> implements PersistenceExceptionTranslator {
|
||||
|
||||
private final Cluster cluster;
|
||||
private final String bucketName;
|
||||
private final String bucketPassword;
|
||||
private final String username;
|
||||
private final String password;
|
||||
|
||||
private final PersistenceExceptionTranslator exceptionTranslator = new CouchbaseExceptionTranslator();
|
||||
|
||||
public CouchbaseBucketFactoryBean(Cluster cluster) {
|
||||
this(cluster, null, null);
|
||||
this(cluster, null, null, null);
|
||||
}
|
||||
|
||||
public CouchbaseBucketFactoryBean(Cluster cluster, String bucketName) {
|
||||
this(cluster, bucketName, null);
|
||||
this(cluster, bucketName, bucketName, null);
|
||||
}
|
||||
|
||||
public CouchbaseBucketFactoryBean(Cluster cluster, String bucketName, String bucketPassword) {
|
||||
public CouchbaseBucketFactoryBean(Cluster cluster, String bucketName, String username, String password) {
|
||||
this.cluster = cluster;
|
||||
this.bucketName = bucketName;
|
||||
this.bucketPassword = bucketPassword;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,11 +66,15 @@ public class CouchbaseBucketFactoryBean extends AbstractFactoryBean<Bucket> impl
|
||||
if (bucketName == null) {
|
||||
return cluster.openBucket();
|
||||
}
|
||||
else if (bucketPassword == null) {
|
||||
else if (password == null) {
|
||||
return cluster.openBucket(bucketName);
|
||||
}
|
||||
else if (bucketName.contentEquals(username)) {
|
||||
return cluster.openBucket(bucketName, password);
|
||||
}
|
||||
else {
|
||||
return cluster.openBucket(bucketName, bucketPassword);
|
||||
cluster.authenticate(username, password);
|
||||
return cluster.openBucket(bucketName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.util.StringUtils;
|
||||
* The parser for XML definition of a {@link Bucket}, to be constructed from a {@link Cluster} reference.
|
||||
* If no reference is given, the default reference <code>{@value BeanNames#COUCHBASE_CLUSTER}</code> is used.
|
||||
*
|
||||
* See attributes {@link #CLUSTER_REF_ATTR}, {@link #BUCKETNAME_ATTR} and {@link #BUCKETPASSWORD_ATTR}.
|
||||
* See attributes {@link #CLUSTER_REF_ATTR}, {@link #BUCKETNAME_ATTR}, {@link #USERNAME_ATTR} and {@link #BUCKETPASSWORD_ATTR}.
|
||||
*
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
@@ -46,8 +46,13 @@ public class CouchbaseBucketParser extends AbstractSingleBeanDefinitionParser {
|
||||
*/
|
||||
public static final String BUCKETNAME_ATTR = "bucketName";
|
||||
|
||||
/*
|
||||
* The <code>username</code> attribute in a bucket definition defines the user of the bucket to open.
|
||||
*/
|
||||
public static final String USERNAME_ATTR = "username";
|
||||
|
||||
/**
|
||||
* The <code>bucketPassword</code> attribute in a bucket definition defines the password of the bucket to open.
|
||||
* The <code>bucketPassword</code> attribute in a bucket definition defines the password of the bucket/user of the bucket to open.
|
||||
*/
|
||||
public static final String BUCKETPASSWORD_ATTR = "bucketPassword";
|
||||
|
||||
@@ -95,9 +100,14 @@ public class CouchbaseBucketParser extends AbstractSingleBeanDefinitionParser {
|
||||
builder.addConstructorArgValue(bucketName);
|
||||
}
|
||||
|
||||
String bucketPassword = element.getAttribute(BUCKETPASSWORD_ATTR);
|
||||
if (StringUtils.hasText(bucketPassword)) {
|
||||
builder.addConstructorArgValue(bucketPassword);
|
||||
String username = element.getAttribute(USERNAME_ATTR);
|
||||
if (StringUtils.hasText(username)) {
|
||||
builder.addConstructorArgValue(username);
|
||||
}
|
||||
|
||||
String password = element.getAttribute(BUCKETPASSWORD_ATTR);
|
||||
if (StringUtils.hasText(password)) {
|
||||
builder.addConstructorArgValue(password);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user