[ https://issues.apache.org/jira/browse/SOLR-15857?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Lamine updated SOLR-15857: -------------------------- Description: https://issues.apache.org/jira/browse/SOLR-15857 **Problem** Solr uses a list of credentials to connect to Zookeeper and to handle ACLs. - 1- In the current implementation, the credentials are passed through command line (system props) or read from a clear text file stored in all cluster hosts. Needless to say this is not safe enough. - 2- On the other hand, the same code to load the credentials is called twice, first by _ZkCredentialsProvider_ to connect to Zookeeper and a second time by _ZkACLProvider_ to create ACLs. The code is also duplicated, although it's only reading from system props. Adding a custom pair of _ZkCredentialsProvider_/_ZkACLProvider_ to load the credentials from another source (ex a Secret Manager) would also require duplicate the code and make repetitive calls to extract the same credentials. - 3- There is no way to customize how credentials are passed without recompiling. **Proposed solution** Let’s start with problem 2). **Problem 2** - Refactor the way how the credentials are injected by passing them as a dependency. One code, called once and injected into the client class. Here the client classes are _ZkCredentialsProvider_ and _ZkACLProvider_. - Favor composition over inheritance to inject custom credentials loaders without changing the composing (container) class. - Add a third interface _ZkCredentialsInjector_ whose implementations load ZK credentials from a credentials source to be injected into _ZkCredentialsProvider_ and _ZkACLProvider_ - The workflow is: Credentials source —> _ZkCredentialsInjector_ --> _ZkCredentialsProvider_/_ZkACLProvider_ --> Zookeeper - The _ZkCredentialsInjector_ gets the creds from an external source which get injected into zkCredentialsProvider and zkACLProvider. The "_external source_" here can be system props, a file, a Secret Manager, or any other local or remote source. ``` public interface ZkCredentialsInjector { List<ZkCredential> getZkCredentials(); ... } ``` - Any class implementing _ZkCredentialsInjector_ can be injected via system props in _solr.ini.sh/cmd_. In the below example _VMParamsZkCredentialsInjector_ is injected. Note: _VMParamsAllAndReadonlyDigestZkACLProvider_ and _VMParamsSingleSetCredentialsDigestZkCredentialsProvider_ would be deprecated and replaced with a combination of _DigestZkACLProvider_/_DigestZkCredentialsProvider_ and _VMParamsZkCredentialsInjector_. ``` SOLR_ZK_CREDS_AND_ACLS=“ -DzkACLProvider=org.apache.solr.common.cloud.acl.DigestZkACLProvider \ -DzkCredentialsProvider=org.apache.solr.common.cloud.acl.DigestZkCredentialsProvider \ -DzkCredentialsInjector=org.apache.solr.common.cloud.acl.VMParamsZkCredentialsInjector \ -DzkDigestUsername=admin-user -DzkDigestPassword=CHANGEME-ADMIN-PASSWORD \ -DzkDigestReadonlyUsername=readonly-user -DzkDigestReadonlyPassword=CHANGEME-READONLY-PASSWORD" SOLR_OPTS="$SOLR_OPTS $SOLR_ZK_CREDS_AND_ACLS" ``` - Add _DigestZkACLProvider_/_DigestZkCredentialsProvider_ classes to support _Digest_ based scheme ZK authentication/authorization ``` Class DigestZkACLProvider implements ZkACLProvider{ CredentialsInjector credentialsInjector; ... } Class DigestZkCredentialsProvider implements ZkCredentialsProvider{ CredentialsInjector credentialsInjector; ... } ``` This concept can be generalized to non-digest schemes (a kind of Strategy pattern) but that would require more refactoring, it can be achieved in a future contribution if this one is accepted. Now apply this new feature and add a custom injector to solve problem 1). **Problem 1** - Store the credentials in a Secret Manager to have Solr pull them out at startup. - Add _SecretCredentialInjector_ class that contains a dependency interface (_SecretCredentialsProvider_) whose implementation pulls zk credentials from a Secret Manager and delegate the _getZkCredentials_ call. ``` public class SecretCredentialInjector implements ZkCredentialsInjector { ... private SecretCredentialsProvider secretCredentialProvider; public List<ZkCredential> getZkCredentials() { ... return secretCredentialProvider.getZkCredentials(secretName); } ... } ``` - In this contribution the offered implementating class is _AWSSecretCredentialsProvider_ that gets zk credentials from AWS Secret Manager. Tu support any other Secret Manager provider all you need to do is add a class implementing _SecretCredentialsProvider_ and pass it through system props (-_DzkSecretCredentialsProvider_) ``` SOLR_ZK_CREDS_AND_ACLS="-DzkACLProvider=org.apache.solr.common.cloud.acl.DigestZkACLProvider \ -DzkCredentialsProvider=org.apache.solr.common.cloud.acl.DigestZkCredentialsProvider \ -DzkCredentialsInjector=org.apache.solr.common.cloud.acl.SecretCredentialInjector \ -DzkSecretCredentialsProvider=org.apache.solr.secret.zk.AWSSecretCredentialsProvider \ -DzkSecretCredentialSecretName=zkSecret \ -DzkCredentialsAWSSecretRegion=us-west-2" SOLR_OPTS="$SOLR_OPTS $SOLR_ZK_CREDS_AND_ACLS" ``` **Problem 3** A new _contrib_ module (_secret-provider_) is added where _SecretCredentialsProvider_ implementing classes can be added without the need to add a new dependency to Solr core. All one needs to do after adding a new class is to pass it through system props via _solr.ini.sh/cmd_ file. This module can be used in the future for other secrets injections, not specifically related to zk. Thank you in advance for your time and your comments. was:In progress... > Add Secret Manager support for ZK ACL credentials > ------------------------------------------------- > > Key: SOLR-15857 > URL: https://issues.apache.org/jira/browse/SOLR-15857 > Project: Solr > Issue Type: Improvement > Security Level: Public(Default Security Level. Issues are Public) > Reporter: Lamine > Priority: Minor > Time Spent: 10m > Remaining Estimate: 0h > > https://issues.apache.org/jira/browse/SOLR-15857 > **Problem** > Solr uses a list of credentials to connect to Zookeeper and to handle ACLs. > - 1- In the current implementation, the credentials are passed through > command line (system props) or read from a clear text file stored in all > cluster hosts. Needless to say this is not safe enough. > - 2- On the other hand, the same code to load the credentials is called > twice, first by _ZkCredentialsProvider_ to connect to Zookeeper and a second > time by _ZkACLProvider_ to create ACLs. The code is also duplicated, although > it's only reading from system props. > Adding a custom pair of _ZkCredentialsProvider_/_ZkACLProvider_ to load the > credentials from another source (ex a Secret Manager) would also require > duplicate the code and make repetitive calls to extract the same credentials. > - 3- There is no way to customize how credentials are passed without > recompiling. > > **Proposed solution** > Let’s start with problem 2). > **Problem 2** > - Refactor the way how the credentials are injected by passing them as a > dependency. One code, called once and injected into the client class. Here > the client classes are _ZkCredentialsProvider_ and _ZkACLProvider_. > - Favor composition over inheritance to inject custom credentials loaders > without changing the composing (container) class. > - Add a third interface _ZkCredentialsInjector_ whose implementations load ZK > credentials from a credentials source to be injected into > _ZkCredentialsProvider_ and _ZkACLProvider_ > - The workflow is: Credentials source —> _ZkCredentialsInjector_ --> > _ZkCredentialsProvider_/_ZkACLProvider_ --> Zookeeper > - The _ZkCredentialsInjector_ gets the creds from an external source which > get injected into zkCredentialsProvider and zkACLProvider. The "_external > source_" here can be system props, a file, a Secret Manager, or any other > local or remote source. > ``` > public interface ZkCredentialsInjector { > List<ZkCredential> getZkCredentials(); > ... > } > ``` > - Any class implementing _ZkCredentialsInjector_ can be injected via system > props in _solr.ini.sh/cmd_. > In the below example _VMParamsZkCredentialsInjector_ is injected. > Note: _VMParamsAllAndReadonlyDigestZkACLProvider_ and > _VMParamsSingleSetCredentialsDigestZkCredentialsProvider_ would be deprecated > and replaced with a combination of > _DigestZkACLProvider_/_DigestZkCredentialsProvider_ and > _VMParamsZkCredentialsInjector_. > ``` > SOLR_ZK_CREDS_AND_ACLS=“ > -DzkACLProvider=org.apache.solr.common.cloud.acl.DigestZkACLProvider \ > > -DzkCredentialsProvider=org.apache.solr.common.cloud.acl.DigestZkCredentialsProvider > \ > > -DzkCredentialsInjector=org.apache.solr.common.cloud.acl.VMParamsZkCredentialsInjector > \ > -DzkDigestUsername=admin-user -DzkDigestPassword=CHANGEME-ADMIN-PASSWORD > \ > -DzkDigestReadonlyUsername=readonly-user > -DzkDigestReadonlyPassword=CHANGEME-READONLY-PASSWORD" > SOLR_OPTS="$SOLR_OPTS $SOLR_ZK_CREDS_AND_ACLS" > ``` > - Add _DigestZkACLProvider_/_DigestZkCredentialsProvider_ classes to support > _Digest_ based scheme ZK authentication/authorization > ``` > Class DigestZkACLProvider implements ZkACLProvider{ > CredentialsInjector credentialsInjector; > ... > } > Class DigestZkCredentialsProvider implements ZkCredentialsProvider{ > CredentialsInjector credentialsInjector; > ... > } > ``` > This concept can be generalized to non-digest schemes (a kind of Strategy > pattern) but that would require more refactoring, it can be achieved in a > future contribution if this one is accepted. > Now apply this new feature and add a custom injector to solve problem 1). > **Problem 1** > - Store the credentials in a Secret Manager to have Solr pull them out at > startup. > - Add _SecretCredentialInjector_ class that contains a dependency interface > (_SecretCredentialsProvider_) whose implementation pulls zk credentials from > a Secret Manager and delegate the _getZkCredentials_ call. > ``` > public class SecretCredentialInjector implements ZkCredentialsInjector { > ... > private SecretCredentialsProvider secretCredentialProvider; > > public List<ZkCredential> getZkCredentials() { > ... > return secretCredentialProvider.getZkCredentials(secretName); > } > ... > } > ``` > - In this contribution the offered implementating class is > _AWSSecretCredentialsProvider_ that gets zk credentials from AWS Secret > Manager. Tu support any other Secret Manager provider all you need to do is > add a class implementing _SecretCredentialsProvider_ and pass it through > system props (-_DzkSecretCredentialsProvider_) > ``` > SOLR_ZK_CREDS_AND_ACLS="-DzkACLProvider=org.apache.solr.common.cloud.acl.DigestZkACLProvider > \ > > -DzkCredentialsProvider=org.apache.solr.common.cloud.acl.DigestZkCredentialsProvider > \ > > -DzkCredentialsInjector=org.apache.solr.common.cloud.acl.SecretCredentialInjector > \ > > -DzkSecretCredentialsProvider=org.apache.solr.secret.zk.AWSSecretCredentialsProvider > \ > -DzkSecretCredentialSecretName=zkSecret \ > -DzkCredentialsAWSSecretRegion=us-west-2" > SOLR_OPTS="$SOLR_OPTS $SOLR_ZK_CREDS_AND_ACLS" > ``` > **Problem 3** > A new _contrib_ module (_secret-provider_) is added where > _SecretCredentialsProvider_ implementing classes can be added without the > need to add a new dependency to Solr core. All one needs to do after adding a > new class is to pass it through system props via _solr.ini.sh/cmd_ file. > This module can be used in the future for other secrets injections, not > specifically related to zk. > > Thank you in advance for your time and your comments. > > -- This message was sent by Atlassian Jira (v8.20.7#820007) --------------------------------------------------------------------- To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org For additional commands, e-mail: issues-h...@solr.apache.org