You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Mark Hull <ma...@gmail.com> on 2017/12/17 01:23:12 UTC

Redacting db user name and password from XML

I apologize if this question has been asked and answered before but: 
What is the best-practices solution to redact the database user name and 
password from an XML file created and used by Cayenne Modeler? The 
ServerRuntime build statement is simply:

cayenneRuntime = ServerRuntime.builder()
.addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
             .build();

It works just fine as long as the db user name and password are in the 
XML file, but I don't believe in leaving clear-text artifacts like that 
laying around in the code, so I want to add the user and password data 
at runtime from a Java method (not from an external file or an 
'executable', whatever that means in the content of PasswordEncoding). 
Adding .user("xyz") and .password("zyx") to the build statement don't 
work, presumably because the DataNode is not the default and those 
statements just set their respective fields for the default DataNode.

If I have to, I can create either a Module to change those properties 
somehow at runtime (though the documentation for doing so is, to be 
kind, sparse), somehow implement the PasswordEncoding (even less 
documentation, because I don't know where it's used), or just edit the 
XML at runtime (horrible choice but looking like the best of a bad lot 
at this point).

All this seems like a lot of effort when I imagine this need must crop 
up fairly often among Cayenne users (it should, for security reasons 
IMO). Is there a simple standard way to do what I want? Or at least a 
standard way? I don't want to invent a new wheel here. I feel like I'm 
missing something obvious that everyone else knows about and that I just 
missed. Oh, by the way, whatever the solution is should still allow 
Cayenne Modeler to function normally.

I promise I searched for the answer everywhere I could think of. 
StackOverflow had a couple answers that used deprecated methods and 
didn't work when I tried them.

Thanks in advance for any help. I hope there's a really simple answer so 
I feel stupid but don't have to spend any more time on this than I have 
already. :)

- Mark Hull

/People say nothing is impossible, but I do nothing every day. - A. A. 
Milne/

Re: Redacting db user name and password from XML

Posted by Mark Hull <ma...@gmail.com>.
I concur. The Java runtime parameter approach will keep the data out of 
the source code, which helps a lot because I can secure the runtime 
environment, but the second option in Andrus' StackOverflow link 
<https://stackoverflow.com/questions/45781378/best-practice-to-manage-apache-cayenne-project-xml-file> 
seems ideal -- 
ServerModule.contributeProperties(binder).put(Constants.JDBC_PASSWORD_PROPERTY, 
"xxxxx").  However, I haven't yet figured out how to get it to work with 
a declared project name
and DataNode yet. If one is just going to use the default DataNode, just 
adding .user() and .password() to the ServerRuntime.builder statement 
should suffice according to docs.

Mark Hull

On 12/18/2017 07:27 PM, Michael Gentry wrote:
> A disadvantage of this approach, though, is it puts the username/password
> on the command-line and/or the process list, plus potentially exposes it in
> command-line history, too.
>
> mrg
>
>
> On Mon, Dec 18, 2017 at 11:49 AM, Andrus Adamchik <an...@objectstyle.org>
> wrote:
>
>> Hi Mark,
>>
>> We've done quite a bit of work in Cayenne to avoid complex things like
>> PasswordEncoding or custom DataSourceFactories. If all that is needed is to
>> change / define login credentials, the simplest way is via properties [1].
>> [2] shows an example with a single DataNode. If you have more than one, you
>> will need to add the project name and the DataNode name to the base
>> property name. E.g.:
>>
>> export MY_USER=user
>> export MY_PASSWORD=secret
>>
>> java -Dcayenne.jdbc.username.project.mynode=$MY_USER \
>>       -Dcayenne.jdbc.password.project.mynode=$MY_PASSWORD \
>>       -jar myapp.jar
>>
>>
>> Hope this helps,
>> Andrus
>>
>> [1] http://cayenne.apache.org/docs/4.0/cayenne-guide/
>> configuration-properties.html
>> [2] https://stackoverflow.com/questions/45781378/best-
>> practice-to-manage-apache-cayenne-project-xml-file
>>
>>
>>
>>> On Dec 17, 2017, at 4:23 AM, Mark Hull <ma...@gmail.com> wrote:
>>>
>>> I apologize if this question has been asked and answered before but:
>> What is the best-practices solution to redact the database user name and
>> password from an XML file created and used by Cayenne Modeler? The
>> ServerRuntime build statement is simply:
>>> cayenneRuntime = ServerRuntime.builder()
>>> .addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
>>>              .build();
>>>
>>> It works just fine as long as the db user name and password are in the
>> XML file, but I don't believe in leaving clear-text artifacts like that
>> laying around in the code, so I want to add the user and password data at
>> runtime from a Java method (not from an external file or an 'executable',
>> whatever that means in the content of PasswordEncoding). Adding
>> .user("xyz") and .password("zyx") to the build statement don't work,
>> presumably because the DataNode is not the default and those statements
>> just set their respective fields for the default DataNode.
>>> If I have to, I can create either a Module to change those properties
>> somehow at runtime (though the documentation for doing so is, to be kind,
>> sparse), somehow implement the PasswordEncoding (even less documentation,
>> because I don't know where it's used), or just edit the XML at runtime
>> (horrible choice but looking like the best of a bad lot at this point).
>>> All this seems like a lot of effort when I imagine this need must crop
>> up fairly often among Cayenne users (it should, for security reasons IMO).
>> Is there a simple standard way to do what I want? Or at least a standard
>> way? I don't want to invent a new wheel here. I feel like I'm missing
>> something obvious that everyone else knows about and that I just missed.
>> Oh, by the way, whatever the solution is should still allow Cayenne Modeler
>> to function normally.
>>> I promise I searched for the answer everywhere I could think of.
>> StackOverflow had a couple answers that used deprecated methods and didn't
>> work when I tried them.
>>> Thanks in advance for any help. I hope there's a really simple answer so
>> I feel stupid but don't have to spend any more time on this than I have
>> already. :)
>>> - Mark Hull
>>>
>>> /People say nothing is impossible, but I do nothing every day. - A. A.
>> Milne/
>>
>>


Re: Redacting db user name and password from XML

Posted by Andrus Adamchik <an...@objectstyle.org>.
Sorry. You are right. Of course the shell will resolve the vars and put the values in the process name. Been living in Bootique world for the last 2 years, so I thought of a different scenario of the env var being read not via System.getProperty(), but rather via System.getenv(). 

So yeah, "-D" is unsafe, but converting shell vars to Cayenne DI properties in the app "main" method should hide the secrets from the causal observer on the app server.

Andrus


> On Dec 19, 2017, at 9:45 AM, Musall, Maik <ma...@selbstdenker.ag> wrote:
> 
> 
>> Am 19.12.2017 um 06:56 schrieb Andrus Adamchik <an...@objectstyle.org>:
>> 
>>> A disadvantage of this approach, though, is it puts the username/password
>>> on the command-line and/or the process list, plus potentially exposes it in
>>> command-line history, too.
>> 
>> It doesn't if you are careful. Nothing prevents you from putting these in a startup script of your app (this is what I was kind of alluding to when I defined credentials as exported vars). From there you have lots of options depending on how paranoid you are:
>> 
>> * restricting access to the script with UNIX permissions.
>> * storing it on an encrypted drive.
>> * creating the script dynamically on startup and then deleting when the app is started.
>> 
>> The point is that with properties you have an easy mechanism separating your security solution away from your Java app.
> 
> As long as those parameters end up as part of the java command line because the shell resolves them and puts them there literally, they will still be discoverable from the process list at runtime for every other user on the machine. The java process itself could redact them from there, but of course it doesn't.
> 
> The credentials would need to live in a separate file with locked down permissions, with that file being referenced by name in the java command line.
> 
> Maik
> 


Re: Redacting db user name and password from XML

Posted by "Musall, Maik" <ma...@selbstdenker.ag>.
> Am 19.12.2017 um 06:56 schrieb Andrus Adamchik <an...@objectstyle.org>:
> 
>> A disadvantage of this approach, though, is it puts the username/password
>> on the command-line and/or the process list, plus potentially exposes it in
>> command-line history, too.
> 
> It doesn't if you are careful. Nothing prevents you from putting these in a startup script of your app (this is what I was kind of alluding to when I defined credentials as exported vars). From there you have lots of options depending on how paranoid you are:
> 
> * restricting access to the script with UNIX permissions.
> * storing it on an encrypted drive.
> * creating the script dynamically on startup and then deleting when the app is started.
> 
> The point is that with properties you have an easy mechanism separating your security solution away from your Java app.

As long as those parameters end up as part of the java command line because the shell resolves them and puts them there literally, they will still be discoverable from the process list at runtime for every other user on the machine. The java process itself could redact them from there, but of course it doesn't.

The credentials would need to live in a separate file with locked down permissions, with that file being referenced by name in the java command line.

Maik


Re: Redacting db user name and password from XML

Posted by Andrus Adamchik <an...@objectstyle.org>.
> A disadvantage of this approach, though, is it puts the username/password
> on the command-line and/or the process list, plus potentially exposes it in
> command-line history, too.

It doesn't if you are careful. Nothing prevents you from putting these in a startup script of your app (this is what I was kind of alluding to when I defined credentials as exported vars). From there you have lots of options depending on how paranoid you are:

* restricting access to the script with UNIX permissions.
* storing it on an encrypted drive.
* creating the script dynamically on startup and then deleting when the app is started.

The point is that with properties you have an easy mechanism separating your security solution away from your Java app.

Andrus


> On Dec 19, 2017, at 4:27 AM, Michael Gentry <bl...@gmail.com> wrote:
> 
> A disadvantage of this approach, though, is it puts the username/password
> on the command-line and/or the process list, plus potentially exposes it in
> command-line history, too.
> 
> mrg
> 
> 
> On Mon, Dec 18, 2017 at 11:49 AM, Andrus Adamchik <an...@objectstyle.org>
> wrote:
> 
>> Hi Mark,
>> 
>> We've done quite a bit of work in Cayenne to avoid complex things like
>> PasswordEncoding or custom DataSourceFactories. If all that is needed is to
>> change / define login credentials, the simplest way is via properties [1].
>> [2] shows an example with a single DataNode. If you have more than one, you
>> will need to add the project name and the DataNode name to the base
>> property name. E.g.:
>> 
>> export MY_USER=user
>> export MY_PASSWORD=secret
>> 
>> java -Dcayenne.jdbc.username.project.mynode=$MY_USER \
>>     -Dcayenne.jdbc.password.project.mynode=$MY_PASSWORD \
>>     -jar myapp.jar
>> 
>> 
>> Hope this helps,
>> Andrus
>> 
>> [1] http://cayenne.apache.org/docs/4.0/cayenne-guide/
>> configuration-properties.html
>> [2] https://stackoverflow.com/questions/45781378/best-
>> practice-to-manage-apache-cayenne-project-xml-file
>> 
>> 
>> 
>>> On Dec 17, 2017, at 4:23 AM, Mark Hull <ma...@gmail.com> wrote:
>>> 
>>> I apologize if this question has been asked and answered before but:
>> What is the best-practices solution to redact the database user name and
>> password from an XML file created and used by Cayenne Modeler? The
>> ServerRuntime build statement is simply:
>>> 
>>> cayenneRuntime = ServerRuntime.builder()
>>> .addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
>>>            .build();
>>> 
>>> It works just fine as long as the db user name and password are in the
>> XML file, but I don't believe in leaving clear-text artifacts like that
>> laying around in the code, so I want to add the user and password data at
>> runtime from a Java method (not from an external file or an 'executable',
>> whatever that means in the content of PasswordEncoding). Adding
>> .user("xyz") and .password("zyx") to the build statement don't work,
>> presumably because the DataNode is not the default and those statements
>> just set their respective fields for the default DataNode.
>>> 
>>> If I have to, I can create either a Module to change those properties
>> somehow at runtime (though the documentation for doing so is, to be kind,
>> sparse), somehow implement the PasswordEncoding (even less documentation,
>> because I don't know where it's used), or just edit the XML at runtime
>> (horrible choice but looking like the best of a bad lot at this point).
>>> 
>>> All this seems like a lot of effort when I imagine this need must crop
>> up fairly often among Cayenne users (it should, for security reasons IMO).
>> Is there a simple standard way to do what I want? Or at least a standard
>> way? I don't want to invent a new wheel here. I feel like I'm missing
>> something obvious that everyone else knows about and that I just missed.
>> Oh, by the way, whatever the solution is should still allow Cayenne Modeler
>> to function normally.
>>> 
>>> I promise I searched for the answer everywhere I could think of.
>> StackOverflow had a couple answers that used deprecated methods and didn't
>> work when I tried them.
>>> 
>>> Thanks in advance for any help. I hope there's a really simple answer so
>> I feel stupid but don't have to spend any more time on this than I have
>> already. :)
>>> 
>>> - Mark Hull
>>> 
>>> /People say nothing is impossible, but I do nothing every day. - A. A.
>> Milne/
>> 
>> 


Re: Redacting db user name and password from XML

Posted by Michael Gentry <bl...@gmail.com>.
A disadvantage of this approach, though, is it puts the username/password
on the command-line and/or the process list, plus potentially exposes it in
command-line history, too.

mrg


On Mon, Dec 18, 2017 at 11:49 AM, Andrus Adamchik <an...@objectstyle.org>
wrote:

> Hi Mark,
>
> We've done quite a bit of work in Cayenne to avoid complex things like
> PasswordEncoding or custom DataSourceFactories. If all that is needed is to
> change / define login credentials, the simplest way is via properties [1].
> [2] shows an example with a single DataNode. If you have more than one, you
> will need to add the project name and the DataNode name to the base
> property name. E.g.:
>
> export MY_USER=user
> export MY_PASSWORD=secret
>
> java -Dcayenne.jdbc.username.project.mynode=$MY_USER \
>      -Dcayenne.jdbc.password.project.mynode=$MY_PASSWORD \
>      -jar myapp.jar
>
>
> Hope this helps,
> Andrus
>
> [1] http://cayenne.apache.org/docs/4.0/cayenne-guide/
> configuration-properties.html
> [2] https://stackoverflow.com/questions/45781378/best-
> practice-to-manage-apache-cayenne-project-xml-file
>
>
>
> > On Dec 17, 2017, at 4:23 AM, Mark Hull <ma...@gmail.com> wrote:
> >
> > I apologize if this question has been asked and answered before but:
> What is the best-practices solution to redact the database user name and
> password from an XML file created and used by Cayenne Modeler? The
> ServerRuntime build statement is simply:
> >
> > cayenneRuntime = ServerRuntime.builder()
> > .addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
> >             .build();
> >
> > It works just fine as long as the db user name and password are in the
> XML file, but I don't believe in leaving clear-text artifacts like that
> laying around in the code, so I want to add the user and password data at
> runtime from a Java method (not from an external file or an 'executable',
> whatever that means in the content of PasswordEncoding). Adding
> .user("xyz") and .password("zyx") to the build statement don't work,
> presumably because the DataNode is not the default and those statements
> just set their respective fields for the default DataNode.
> >
> > If I have to, I can create either a Module to change those properties
> somehow at runtime (though the documentation for doing so is, to be kind,
> sparse), somehow implement the PasswordEncoding (even less documentation,
> because I don't know where it's used), or just edit the XML at runtime
> (horrible choice but looking like the best of a bad lot at this point).
> >
> > All this seems like a lot of effort when I imagine this need must crop
> up fairly often among Cayenne users (it should, for security reasons IMO).
> Is there a simple standard way to do what I want? Or at least a standard
> way? I don't want to invent a new wheel here. I feel like I'm missing
> something obvious that everyone else knows about and that I just missed.
> Oh, by the way, whatever the solution is should still allow Cayenne Modeler
> to function normally.
> >
> > I promise I searched for the answer everywhere I could think of.
> StackOverflow had a couple answers that used deprecated methods and didn't
> work when I tried them.
> >
> > Thanks in advance for any help. I hope there's a really simple answer so
> I feel stupid but don't have to spend any more time on this than I have
> already. :)
> >
> > - Mark Hull
> >
> > /People say nothing is impossible, but I do nothing every day. - A. A.
> Milne/
>
>

Re: Redacting db user name and password from XML

Posted by Mark Hull <ma...@gmail.com>.
Great, I knew you had to have something like this. I had encountered 
these configuration properties before in my research but I didn't quite 
realize they could be used as Java runtime properties. These will work 
quite well, I think. Is there a standard way to use them in the Modeler, 
so they don't end up in XML? I'm going to look myself right now to see; 
I'm sure there's an easy way.

Andrus, thank you very much for responding. I should add at this point 
that I think Cayenne is a remarkable product, and I rely on it and use 
it every time I need a relational database management system in a 
project. Cayenne is a great project and your collective work is a huge 
help to all of us in the trenches.

Cheers and thanks again,

Mark Hull


On 12/18/2017 10:49 AM, Andrus Adamchik wrote:
> Hi Mark,
>
> We've done quite a bit of work in Cayenne to avoid complex things like PasswordEncoding or custom DataSourceFactories. If all that is needed is to change / define login credentials, the simplest way is via properties [1]. [2] shows an example with a single DataNode. If you have more than one, you will need to add the project name and the DataNode name to the base property name. E.g.:
>
> export MY_USER=user
> export MY_PASSWORD=secret
>
> java -Dcayenne.jdbc.username.project.mynode=$MY_USER \
>       -Dcayenne.jdbc.password.project.mynode=$MY_PASSWORD \
>       -jar myapp.jar
>
>
> Hope this helps,
> Andrus
>
> [1] http://cayenne.apache.org/docs/4.0/cayenne-guide/configuration-properties.html
> [2] https://stackoverflow.com/questions/45781378/best-practice-to-manage-apache-cayenne-project-xml-file
>
>
>
>> On Dec 17, 2017, at 4:23 AM, Mark Hull <ma...@gmail.com> wrote:
>>
>> I apologize if this question has been asked and answered before but: What is the best-practices solution to redact the database user name and password from an XML file created and used by Cayenne Modeler? The ServerRuntime build statement is simply:
>>
>> cayenneRuntime = ServerRuntime.builder()
>> .addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
>>              .build();
>>
>> It works just fine as long as the db user name and password are in the XML file, but I don't believe in leaving clear-text artifacts like that laying around in the code, so I want to add the user and password data at runtime from a Java method (not from an external file or an 'executable', whatever that means in the content of PasswordEncoding). Adding .user("xyz") and .password("zyx") to the build statement don't work, presumably because the DataNode is not the default and those statements just set their respective fields for the default DataNode.
>>
>> If I have to, I can create either a Module to change those properties somehow at runtime (though the documentation for doing so is, to be kind, sparse), somehow implement the PasswordEncoding (even less documentation, because I don't know where it's used), or just edit the XML at runtime (horrible choice but looking like the best of a bad lot at this point).
>>
>> All this seems like a lot of effort when I imagine this need must crop up fairly often among Cayenne users (it should, for security reasons IMO). Is there a simple standard way to do what I want? Or at least a standard way? I don't want to invent a new wheel here. I feel like I'm missing something obvious that everyone else knows about and that I just missed. Oh, by the way, whatever the solution is should still allow Cayenne Modeler to function normally.
>>
>> I promise I searched for the answer everywhere I could think of. StackOverflow had a couple answers that used deprecated methods and didn't work when I tried them.
>>
>> Thanks in advance for any help. I hope there's a really simple answer so I feel stupid but don't have to spend any more time on this than I have already. :)
>>
>> - Mark Hull
>>
>> /People say nothing is impossible, but I do nothing every day. - A. A. Milne/
>

-- 
- Hulles

/People say nothing is impossible, but I do nothing every day. - A. A. 
Milne/

Re: Redacting db user name and password from XML

Posted by Andrus Adamchik <an...@objectstyle.org>.
Researching now... One possible difference in my code may be that I don't even model a DataNode in the Modeler. It is added as a DataSource in runtime. So a bug may have crept in for the other scenario.

Andrus

> On Jan 17, 2018, at 3:57 PM, Amedeo Mantica <am...@me.com> wrote:
> 
> I tried setting connection dictionary programmactically too, I was succesful, but only after deletion of the existing connection discionary from the xml
> 
> In my module:
> 
> String driver = conf.getString(JDBC_DRIVER_PROPERTY);
> String jdbcUrl = conf.getString(JDBC_URL_PROPERTY);
> String username = conf.getString(JDBC_USERNAME_PROPERTY);
> String password = conf.hasPath(JDBC_PASSWORD_PROPERTY) ? conf.getString(JDBC_PASSWORD_PROPERTY) : "";
> 
> if(jdbcUrl != null) {
>    binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.JDBC_DRIVER_PROPERTY, driver);
>    binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.JDBC_URL_PROPERTY, jdbcUrl);
>    binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.JDBC_USERNAME_PROPERTY, username);
>    binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.JDBC_PASSWORD_PROPERTY, password);
> }
> 
> Regards
> Amedeo
> 
>> On 17 Jan 2018, at 13:53, Pascal Robert <pr...@druide.com> wrote:
>> 
>> It’s not a Bootique project, it’s a plain old Java project that I run in Eclipse. I can read the properties with System.getProperty, but Cayenne is still using the user and password from the model.
>> 
>> INFO [main] (XMLDataChannelDescriptorLoader.java:125) - Loading XML configuration resource from file:/Users/probert/Code/modele-migration-filemaker/target/classes/cayenne-mysql.xml
>> DEBUG [main] (DefaultHandlerFactory.java:38) - Skipping unknown tag <http://cayenne.apache.org/schema/10/domain:domain>
>> INFO [main] (DataChannelChildrenHandler.java:106) - Loading XML DataMap resource from file:/Users/probert/Code/modele-migration-filemaker/target/classes/mysql.map.xml
>> INFO [main] (DataSourceChildrenHandler.java:81) - loading user name and password.
>> DEBUG [main] (DataDomainProvider.java:240) - finished configuration loading in 62 ms.
>> INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from adresse to ecole
>> INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from don_ecole to ecole
>> INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from no_serie to licence
>> INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from regroupement to utilisateur
>> INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from etat_utilisateur to utilisateur_etats
>> INFO [main] (DriverDataSource.java:179) - Connecting to 'jdbc:mysql://localhost:3306/services_web' as 'xxxx'
>> INFO [main] (DriverDataSource.java:170) - *** Connecting: FAILURE.
>> java.sql.SQLException: Access denied for user 'xxxx'@'localhost' (using password: YES)
>> 
>> I have tried with both -Dcayenne.jdbc.username.mysql.mysql=root and -Dcayenne.jdbc.username=root
>> 
>>> Le 17 janv. 2018 à 00:58, Andrus Adamchik <an...@objectstyle.org> a écrit :
>>> 
>>> If it is not a Bootique project, the property should work. A few non-Bootique projects that I still have (that are on Cayenne 4.0) are started using -Dcayenne.* properties from the docs.
>>> 
>>> If it is a Bootique project, you will need to use the Bootique approach to configure credentials for anything [1], Cayenne included. E.g. for a sample config [2], you'd be setting a value for the property "-Dbq.jdbc.mysql.password". Another way (preferred to -D IMO) is to define a shell variable pointing to the same property, and then exporting the var:
>>> 
>>> in MyModule.java:
>>> 
>>> BQCoreModule.extend(binder)
>>>   .declareVar("jdbc.mysql.username", "DB_USER");
>>>   .declareVar("jdbc.mysql.password", "DB_PASSWORD");
>>> 
>>> in startup script:
>>> 
>>> export DB_PASSWORD=root
>>> export DB_PASSWORD=secret
>>> 
>>> java -jar my.jar # no password in the Java process sig
>>> 
>>> Andrus
>>> 
>>> [1] http://bootique.io/docs/0/bootique-docs/index.html#chapter-7-configuration-and-configurable-factories
>>> [2] https://github.com/bootique-examples/bootique-cayenne-demo/blob/master/config.yml
>>> 
>>>> On Jan 17, 2018, at 12:22 AM, Pascal Robert <pr...@druide.com> wrote:
>>>> 
>>>> Do -Dcayenne.jdbc.username really work? I’m trying to use that (so that the password is not stored in Git), and the runtime is still using the login information from the XML file.
>>>> 
>>>> Cayenne 4.1.M1.
>>>> ServerRuntime mysqlRuntime = ServerRuntime.builder().addConfig("cayenne-mysql.xml").build();
>>>> 
>>>>> Le 18 déc. 2017 à 11:49, Andrus Adamchik <an...@objectstyle.org> a écrit :
>>>>> 
>>>>> Hi Mark,
>>>>> 
>>>>> We've done quite a bit of work in Cayenne to avoid complex things like PasswordEncoding or custom DataSourceFactories. If all that is needed is to change / define login credentials, the simplest way is via properties [1]. [2] shows an example with a single DataNode. If you have more than one, you will need to add the project name and the DataNode name to the base property name. E.g.:
>>>>> 
>>>>> export MY_USER=user
>>>>> export MY_PASSWORD=secret
>>>>> 
>>>>> java -Dcayenne.jdbc.username.project.mynode=$MY_USER \
>>>>> -Dcayenne.jdbc.password.project.mynode=$MY_PASSWORD \
>>>>> -jar myapp.jar 
>>>>> 
>>>>> 
>>>>> Hope this helps,
>>>>> Andrus
>>>>> 
>>>>> [1] http://cayenne.apache.org/docs/4.0/cayenne-guide/configuration-properties.html
>>>>> [2] https://stackoverflow.com/questions/45781378/best-practice-to-manage-apache-cayenne-project-xml-file
>>>>> 
>>>>> 
>>>>> 
>>>>>> On Dec 17, 2017, at 4:23 AM, Mark Hull <ma...@gmail.com> wrote:
>>>>>> 
>>>>>> I apologize if this question has been asked and answered before but: What is the best-practices solution to redact the database user name and password from an XML file created and used by Cayenne Modeler? The ServerRuntime build statement is simply:
>>>>>> 
>>>>>> cayenneRuntime = ServerRuntime.builder()
>>>>>> .addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
>>>>>>        .build();
>>>>>> 
>>>>>> It works just fine as long as the db user name and password are in the XML file, but I don't believe in leaving clear-text artifacts like that laying around in the code, so I want to add the user and password data at runtime from a Java method (not from an external file or an 'executable', whatever that means in the content of PasswordEncoding). Adding .user("xyz") and .password("zyx") to the build statement don't work, presumably because the DataNode is not the default and those statements just set their respective fields for the default DataNode.
>>>>>> 
>>>>>> If I have to, I can create either a Module to change those properties somehow at runtime (though the documentation for doing so is, to be kind, sparse), somehow implement the PasswordEncoding (even less documentation, because I don't know where it's used), or just edit the XML at runtime (horrible choice but looking like the best of a bad lot at this point).
>>>>>> 
>>>>>> All this seems like a lot of effort when I imagine this need must crop up fairly often among Cayenne users (it should, for security reasons IMO). Is there a simple standard way to do what I want? Or at least a standard way? I don't want to invent a new wheel here. I feel like I'm missing something obvious that everyone else knows about and that I just missed. Oh, by the way, whatever the solution is should still allow Cayenne Modeler to function normally.
>>>>>> 
>>>>>> I promise I searched for the answer everywhere I could think of. StackOverflow had a couple answers that used deprecated methods and didn't work when I tried them.
>>>>>> 
>>>>>> Thanks in advance for any help. I hope there's a really simple answer so I feel stupid but don't have to spend any more time on this than I have already. :)
>>>>>> 
>>>>>> - Mark Hull
>>>>>> 
>>>>>> /People say nothing is impossible, but I do nothing every day. - A. A. Milne/
>>>>> 
>>>> 
>>> 
>> 
> 


Re: Redacting db user name and password from XML

Posted by Amedeo Mantica <am...@me.com>.
I tried setting connection dictionary programmactically too, I was succesful, but only after deletion of the existing connection discionary from the xml

In my module:

String driver = conf.getString(JDBC_DRIVER_PROPERTY);
String jdbcUrl = conf.getString(JDBC_URL_PROPERTY);
String username = conf.getString(JDBC_USERNAME_PROPERTY);
String password = conf.hasPath(JDBC_PASSWORD_PROPERTY) ? conf.getString(JDBC_PASSWORD_PROPERTY) : "";

if(jdbcUrl != null) {
    binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.JDBC_DRIVER_PROPERTY, driver);
    binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.JDBC_URL_PROPERTY, jdbcUrl);
    binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.JDBC_USERNAME_PROPERTY, username);
    binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.JDBC_PASSWORD_PROPERTY, password);
}

Regards
Amedeo

> On 17 Jan 2018, at 13:53, Pascal Robert <pr...@druide.com> wrote:
> 
> It’s not a Bootique project, it’s a plain old Java project that I run in Eclipse. I can read the properties with System.getProperty, but Cayenne is still using the user and password from the model.
> 
> INFO [main] (XMLDataChannelDescriptorLoader.java:125) - Loading XML configuration resource from file:/Users/probert/Code/modele-migration-filemaker/target/classes/cayenne-mysql.xml
> DEBUG [main] (DefaultHandlerFactory.java:38) - Skipping unknown tag <http://cayenne.apache.org/schema/10/domain:domain>
> INFO [main] (DataChannelChildrenHandler.java:106) - Loading XML DataMap resource from file:/Users/probert/Code/modele-migration-filemaker/target/classes/mysql.map.xml
> INFO [main] (DataSourceChildrenHandler.java:81) - loading user name and password.
> DEBUG [main] (DataDomainProvider.java:240) - finished configuration loading in 62 ms.
> INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from adresse to ecole
> INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from don_ecole to ecole
> INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from no_serie to licence
> INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from regroupement to utilisateur
> INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from etat_utilisateur to utilisateur_etats
> INFO [main] (DriverDataSource.java:179) - Connecting to 'jdbc:mysql://localhost:3306/services_web' as 'xxxx'
> INFO [main] (DriverDataSource.java:170) - *** Connecting: FAILURE.
> java.sql.SQLException: Access denied for user 'xxxx'@'localhost' (using password: YES)
> 
> I have tried with both -Dcayenne.jdbc.username.mysql.mysql=root and -Dcayenne.jdbc.username=root
> 
>> Le 17 janv. 2018 à 00:58, Andrus Adamchik <an...@objectstyle.org> a écrit :
>> 
>> If it is not a Bootique project, the property should work. A few non-Bootique projects that I still have (that are on Cayenne 4.0) are started using -Dcayenne.* properties from the docs.
>> 
>> If it is a Bootique project, you will need to use the Bootique approach to configure credentials for anything [1], Cayenne included. E.g. for a sample config [2], you'd be setting a value for the property "-Dbq.jdbc.mysql.password". Another way (preferred to -D IMO) is to define a shell variable pointing to the same property, and then exporting the var:
>> 
>> in MyModule.java:
>> 
>>  BQCoreModule.extend(binder)
>>    .declareVar("jdbc.mysql.username", "DB_USER");
>>    .declareVar("jdbc.mysql.password", "DB_PASSWORD");
>> 
>> in startup script:
>> 
>>  export DB_PASSWORD=root
>>  export DB_PASSWORD=secret
>> 
>>  java -jar my.jar # no password in the Java process sig
>> 
>> Andrus
>> 
>> [1] http://bootique.io/docs/0/bootique-docs/index.html#chapter-7-configuration-and-configurable-factories
>> [2] https://github.com/bootique-examples/bootique-cayenne-demo/blob/master/config.yml
>> 
>>> On Jan 17, 2018, at 12:22 AM, Pascal Robert <pr...@druide.com> wrote:
>>> 
>>> Do -Dcayenne.jdbc.username really work? I’m trying to use that (so that the password is not stored in Git), and the runtime is still using the login information from the XML file.
>>> 
>>> Cayenne 4.1.M1.
>>> ServerRuntime mysqlRuntime = ServerRuntime.builder().addConfig("cayenne-mysql.xml").build();
>>> 
>>>> Le 18 déc. 2017 à 11:49, Andrus Adamchik <an...@objectstyle.org> a écrit :
>>>> 
>>>> Hi Mark,
>>>> 
>>>> We've done quite a bit of work in Cayenne to avoid complex things like PasswordEncoding or custom DataSourceFactories. If all that is needed is to change / define login credentials, the simplest way is via properties [1]. [2] shows an example with a single DataNode. If you have more than one, you will need to add the project name and the DataNode name to the base property name. E.g.:
>>>> 
>>>> export MY_USER=user
>>>> export MY_PASSWORD=secret
>>>> 
>>>> java -Dcayenne.jdbc.username.project.mynode=$MY_USER \
>>>>  -Dcayenne.jdbc.password.project.mynode=$MY_PASSWORD \
>>>>  -jar myapp.jar 
>>>> 
>>>> 
>>>> Hope this helps,
>>>> Andrus
>>>> 
>>>> [1] http://cayenne.apache.org/docs/4.0/cayenne-guide/configuration-properties.html
>>>> [2] https://stackoverflow.com/questions/45781378/best-practice-to-manage-apache-cayenne-project-xml-file
>>>> 
>>>> 
>>>> 
>>>>> On Dec 17, 2017, at 4:23 AM, Mark Hull <ma...@gmail.com> wrote:
>>>>> 
>>>>> I apologize if this question has been asked and answered before but: What is the best-practices solution to redact the database user name and password from an XML file created and used by Cayenne Modeler? The ServerRuntime build statement is simply:
>>>>> 
>>>>> cayenneRuntime = ServerRuntime.builder()
>>>>> .addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
>>>>>         .build();
>>>>> 
>>>>> It works just fine as long as the db user name and password are in the XML file, but I don't believe in leaving clear-text artifacts like that laying around in the code, so I want to add the user and password data at runtime from a Java method (not from an external file or an 'executable', whatever that means in the content of PasswordEncoding). Adding .user("xyz") and .password("zyx") to the build statement don't work, presumably because the DataNode is not the default and those statements just set their respective fields for the default DataNode.
>>>>> 
>>>>> If I have to, I can create either a Module to change those properties somehow at runtime (though the documentation for doing so is, to be kind, sparse), somehow implement the PasswordEncoding (even less documentation, because I don't know where it's used), or just edit the XML at runtime (horrible choice but looking like the best of a bad lot at this point).
>>>>> 
>>>>> All this seems like a lot of effort when I imagine this need must crop up fairly often among Cayenne users (it should, for security reasons IMO). Is there a simple standard way to do what I want? Or at least a standard way? I don't want to invent a new wheel here. I feel like I'm missing something obvious that everyone else knows about and that I just missed. Oh, by the way, whatever the solution is should still allow Cayenne Modeler to function normally.
>>>>> 
>>>>> I promise I searched for the answer everywhere I could think of. StackOverflow had a couple answers that used deprecated methods and didn't work when I tried them.
>>>>> 
>>>>> Thanks in advance for any help. I hope there's a really simple answer so I feel stupid but don't have to spend any more time on this than I have already. :)
>>>>> 
>>>>> - Mark Hull
>>>>> 
>>>>> /People say nothing is impossible, but I do nothing every day. - A. A. Milne/
>>>> 
>>> 
>> 
> 


Re: Redacting db user name and password from XML

Posted by Pascal Robert <pr...@druide.com>.
It’s not a Bootique project, it’s a plain old Java project that I run in Eclipse. I can read the properties with System.getProperty, but Cayenne is still using the user and password from the model.

 INFO [main] (XMLDataChannelDescriptorLoader.java:125) - Loading XML configuration resource from file:/Users/probert/Code/modele-migration-filemaker/target/classes/cayenne-mysql.xml
DEBUG [main] (DefaultHandlerFactory.java:38) - Skipping unknown tag <http://cayenne.apache.org/schema/10/domain:domain>
 INFO [main] (DataChannelChildrenHandler.java:106) - Loading XML DataMap resource from file:/Users/probert/Code/modele-migration-filemaker/target/classes/mysql.map.xml
 INFO [main] (DataSourceChildrenHandler.java:81) - loading user name and password.
DEBUG [main] (DataDomainProvider.java:240) - finished configuration loading in 62 ms.
 INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from adresse to ecole
 INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from don_ecole to ecole
 INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from no_serie to licence
 INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from regroupement to utilisateur
 INFO [main] (EntityResolver.java:118) - added runtime complimentary DbRelationship from etat_utilisateur to utilisateur_etats
 INFO [main] (DriverDataSource.java:179) - Connecting to 'jdbc:mysql://localhost:3306/services_web' as 'xxxx'
 INFO [main] (DriverDataSource.java:170) - *** Connecting: FAILURE.
java.sql.SQLException: Access denied for user 'xxxx'@'localhost' (using password: YES)

I have tried with both -Dcayenne.jdbc.username.mysql.mysql=root and -Dcayenne.jdbc.username=root

> Le 17 janv. 2018 à 00:58, Andrus Adamchik <an...@objectstyle.org> a écrit :
> 
> If it is not a Bootique project, the property should work. A few non-Bootique projects that I still have (that are on Cayenne 4.0) are started using -Dcayenne.* properties from the docs.
> 
> If it is a Bootique project, you will need to use the Bootique approach to configure credentials for anything [1], Cayenne included. E.g. for a sample config [2], you'd be setting a value for the property "-Dbq.jdbc.mysql.password". Another way (preferred to -D IMO) is to define a shell variable pointing to the same property, and then exporting the var:
> 
> in MyModule.java:
> 
>   BQCoreModule.extend(binder)
>     .declareVar("jdbc.mysql.username", "DB_USER");
>     .declareVar("jdbc.mysql.password", "DB_PASSWORD");
> 
> in startup script:
> 
>   export DB_PASSWORD=root
>   export DB_PASSWORD=secret
> 
>   java -jar my.jar # no password in the Java process sig
> 
> Andrus
> 
> [1] http://bootique.io/docs/0/bootique-docs/index.html#chapter-7-configuration-and-configurable-factories
> [2] https://github.com/bootique-examples/bootique-cayenne-demo/blob/master/config.yml
> 
>> On Jan 17, 2018, at 12:22 AM, Pascal Robert <pr...@druide.com> wrote:
>> 
>> Do -Dcayenne.jdbc.username really work? I’m trying to use that (so that the password is not stored in Git), and the runtime is still using the login information from the XML file.
>> 
>> Cayenne 4.1.M1.
>> ServerRuntime mysqlRuntime = ServerRuntime.builder().addConfig("cayenne-mysql.xml").build();
>> 
>>> Le 18 déc. 2017 à 11:49, Andrus Adamchik <an...@objectstyle.org> a écrit :
>>> 
>>> Hi Mark,
>>> 
>>> We've done quite a bit of work in Cayenne to avoid complex things like PasswordEncoding or custom DataSourceFactories. If all that is needed is to change / define login credentials, the simplest way is via properties [1]. [2] shows an example with a single DataNode. If you have more than one, you will need to add the project name and the DataNode name to the base property name. E.g.:
>>> 
>>> export MY_USER=user
>>> export MY_PASSWORD=secret
>>> 
>>> java -Dcayenne.jdbc.username.project.mynode=$MY_USER \
>>>   -Dcayenne.jdbc.password.project.mynode=$MY_PASSWORD \
>>>   -jar myapp.jar 
>>> 
>>> 
>>> Hope this helps,
>>> Andrus
>>> 
>>> [1] http://cayenne.apache.org/docs/4.0/cayenne-guide/configuration-properties.html
>>> [2] https://stackoverflow.com/questions/45781378/best-practice-to-manage-apache-cayenne-project-xml-file
>>> 
>>> 
>>> 
>>>> On Dec 17, 2017, at 4:23 AM, Mark Hull <ma...@gmail.com> wrote:
>>>> 
>>>> I apologize if this question has been asked and answered before but: What is the best-practices solution to redact the database user name and password from an XML file created and used by Cayenne Modeler? The ServerRuntime build statement is simply:
>>>> 
>>>> cayenneRuntime = ServerRuntime.builder()
>>>> .addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
>>>>          .build();
>>>> 
>>>> It works just fine as long as the db user name and password are in the XML file, but I don't believe in leaving clear-text artifacts like that laying around in the code, so I want to add the user and password data at runtime from a Java method (not from an external file or an 'executable', whatever that means in the content of PasswordEncoding). Adding .user("xyz") and .password("zyx") to the build statement don't work, presumably because the DataNode is not the default and those statements just set their respective fields for the default DataNode.
>>>> 
>>>> If I have to, I can create either a Module to change those properties somehow at runtime (though the documentation for doing so is, to be kind, sparse), somehow implement the PasswordEncoding (even less documentation, because I don't know where it's used), or just edit the XML at runtime (horrible choice but looking like the best of a bad lot at this point).
>>>> 
>>>> All this seems like a lot of effort when I imagine this need must crop up fairly often among Cayenne users (it should, for security reasons IMO). Is there a simple standard way to do what I want? Or at least a standard way? I don't want to invent a new wheel here. I feel like I'm missing something obvious that everyone else knows about and that I just missed. Oh, by the way, whatever the solution is should still allow Cayenne Modeler to function normally.
>>>> 
>>>> I promise I searched for the answer everywhere I could think of. StackOverflow had a couple answers that used deprecated methods and didn't work when I tried them.
>>>> 
>>>> Thanks in advance for any help. I hope there's a really simple answer so I feel stupid but don't have to spend any more time on this than I have already. :)
>>>> 
>>>> - Mark Hull
>>>> 
>>>> /People say nothing is impossible, but I do nothing every day. - A. A. Milne/
>>> 
>> 
> 


Re: Redacting db user name and password from XML

Posted by Andrus Adamchik <an...@objectstyle.org>.
If it is not a Bootique project, the property should work. A few non-Bootique projects that I still have (that are on Cayenne 4.0) are started using -Dcayenne.* properties from the docs.

If it is a Bootique project, you will need to use the Bootique approach to configure credentials for anything [1], Cayenne included. E.g. for a sample config [2], you'd be setting a value for the property "-Dbq.jdbc.mysql.password". Another way (preferred to -D IMO) is to define a shell variable pointing to the same property, and then exporting the var:

in MyModule.java:

   BQCoreModule.extend(binder)
     .declareVar("jdbc.mysql.username", "DB_USER");
     .declareVar("jdbc.mysql.password", "DB_PASSWORD");

in startup script:

   export DB_PASSWORD=root
   export DB_PASSWORD=secret

   java -jar my.jar # no password in the Java process sig

Andrus

[1] http://bootique.io/docs/0/bootique-docs/index.html#chapter-7-configuration-and-configurable-factories
[2] https://github.com/bootique-examples/bootique-cayenne-demo/blob/master/config.yml

> On Jan 17, 2018, at 12:22 AM, Pascal Robert <pr...@druide.com> wrote:
> 
> Do -Dcayenne.jdbc.username really work? I’m trying to use that (so that the password is not stored in Git), and the runtime is still using the login information from the XML file.
> 
> Cayenne 4.1.M1.
> ServerRuntime mysqlRuntime = ServerRuntime.builder().addConfig("cayenne-mysql.xml").build();
> 
>> Le 18 déc. 2017 à 11:49, Andrus Adamchik <an...@objectstyle.org> a écrit :
>> 
>> Hi Mark,
>> 
>> We've done quite a bit of work in Cayenne to avoid complex things like PasswordEncoding or custom DataSourceFactories. If all that is needed is to change / define login credentials, the simplest way is via properties [1]. [2] shows an example with a single DataNode. If you have more than one, you will need to add the project name and the DataNode name to the base property name. E.g.:
>> 
>> export MY_USER=user
>> export MY_PASSWORD=secret
>> 
>> java -Dcayenne.jdbc.username.project.mynode=$MY_USER \
>>    -Dcayenne.jdbc.password.project.mynode=$MY_PASSWORD \
>>    -jar myapp.jar 
>> 
>> 
>> Hope this helps,
>> Andrus
>> 
>> [1] http://cayenne.apache.org/docs/4.0/cayenne-guide/configuration-properties.html
>> [2] https://stackoverflow.com/questions/45781378/best-practice-to-manage-apache-cayenne-project-xml-file
>> 
>> 
>> 
>>> On Dec 17, 2017, at 4:23 AM, Mark Hull <ma...@gmail.com> wrote:
>>> 
>>> I apologize if this question has been asked and answered before but: What is the best-practices solution to redact the database user name and password from an XML file created and used by Cayenne Modeler? The ServerRuntime build statement is simply:
>>> 
>>> cayenneRuntime = ServerRuntime.builder()
>>> .addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
>>>           .build();
>>> 
>>> It works just fine as long as the db user name and password are in the XML file, but I don't believe in leaving clear-text artifacts like that laying around in the code, so I want to add the user and password data at runtime from a Java method (not from an external file or an 'executable', whatever that means in the content of PasswordEncoding). Adding .user("xyz") and .password("zyx") to the build statement don't work, presumably because the DataNode is not the default and those statements just set their respective fields for the default DataNode.
>>> 
>>> If I have to, I can create either a Module to change those properties somehow at runtime (though the documentation for doing so is, to be kind, sparse), somehow implement the PasswordEncoding (even less documentation, because I don't know where it's used), or just edit the XML at runtime (horrible choice but looking like the best of a bad lot at this point).
>>> 
>>> All this seems like a lot of effort when I imagine this need must crop up fairly often among Cayenne users (it should, for security reasons IMO). Is there a simple standard way to do what I want? Or at least a standard way? I don't want to invent a new wheel here. I feel like I'm missing something obvious that everyone else knows about and that I just missed. Oh, by the way, whatever the solution is should still allow Cayenne Modeler to function normally.
>>> 
>>> I promise I searched for the answer everywhere I could think of. StackOverflow had a couple answers that used deprecated methods and didn't work when I tried them.
>>> 
>>> Thanks in advance for any help. I hope there's a really simple answer so I feel stupid but don't have to spend any more time on this than I have already. :)
>>> 
>>> - Mark Hull
>>> 
>>> /People say nothing is impossible, but I do nothing every day. - A. A. Milne/
>> 
> 


RE: Redacting db user name and password from XML

Posted by "Meeks, Andrew" <an...@vt.edu>.
Hi John, 

Well, when I tried only providing the url and driver the username and password from the xml file.  So, rather than failing with an exception during startup, Cayenne would just have a bad username password error later on when it first tried to establish a connection.  Min connection pool and max connection pool were also undefined during that attempt even though everything was still define in my xml.  Therefore I extrapolated that once Cayenne had TRUE for shouldConfigureDataSourceFromProperties, it ignored anything within the <data-source> element.  
You are correct, it would take more debugging to see if there is a different piece of logic causing things other than url and driver to be ignored.


-----Original Message-----
From: John Huss <jo...@gmail.com> 
Sent: Wednesday, July 18, 2018 2:33 PM
To: user@cayenne.apache.org
Subject: Re: Redacting db user name and password from XML

On Wed, Jul 18, 2018 at 1:26 PM Meeks, Andrew <an...@vt.edu> wrote:

> I feel as though a recent bit of code is closely related to the topic in
> this old thread.   The Cayenne <data-source> xml element supports a
> password with a path external to the application.  The observed 
> environment properties appear to only include JDBC_PASSWORD_PROPERTY 
> which seems to only support a literal password.  For Spring 
> developers, an integration suggestion is included below.
>
> I would like to say, in agreement with the earlier thread, that the 
> documentation at:
> https://cayenne.apache.org/docs/4.1/cayenne-guide/#appendix-a-configur
> ation-properties is unclear in one respect.  I think it needs to state 
> that all
> cayenne.jdbc.* properties must be defined in order for environment 
> properties to override (or correctly override) the definition of 
> data-source in the xml file.  That would have saved me a lot of 
> stepping into code before I found what was happening in DelegatingDataSourceFactory.
> shouldConfigureDataSourceFromProperties(DataNodeDescriptor
> dataNodeDescriptor);
>

I believe only the URL and driver have to be specified via properties in order for them to override the values in the cayenne project file. This is still not really intuitive, but it's better than all of them being required.


>
> If you have a Spring Project and would like to control your 
> <data-source> through a more spring-like configuration, here are 
> relevant snippets from files of how I set it up based on examples in the cayenne documentation:
>
> -- file: application.properties --
> cayenne.jdbc.driver=oracle.jdbc.driver.OracleDriver
> cayenne.jdbc.max_connections=20
> cayenne.jdbc.min_connections=1
> cayenne.jdbc.username=SCOTT
>
> --file: application-dev.properties--
>
> cayenne.jdbc.passwordSource=C:\\home\\apps-config\\testProject\\cayenn
> e_pw.txt cayenne.jdbc.url=jdbc:oracle:thin:@//localhost:1521/xe
>
> --file: application-prod.properties--
>
> cayenne.jdbc.passwordSource=C:\\home\\apps-config\\testProject\\cayenn
> e_pw_prod.txt 
> cayenne.jdbc.url=jdbc:oracle:thin:@//prod.db.example.com:1521/prod_svc
>
> --file: SpringMvcConfig.java--
> @Configuration
> public class MvcConfig extends WebMvcConfigurerAdapter {
>         @Value("${cayenne.jdbc.url}")
>         String cayenneClientUrl;
>
>         @Value("${cayenne.jdbc.driver}")
>         String cayenneDriverProperty;
>
>         @Value("${cayenne.jdbc.passwordSource}")
>         String cayennePasswordSource;
>
>         @Value("${cayenne.jdbc.username}")
>         String cayenneUsername;
>
>         @Value("${cayenne.jdbc.min_connections}")
>         String cayenneMinConnections;
>
>         @Value("${cayenne.jdbc.max_connections}")
>         String cayenneMaxConnections;
>
>         @Bean(name="serverRuntime")
>         public ServerRuntime serverRuntime(){
>
>                 String url = cayenneClientUrl;
>                 String driver = cayenneDriverProperty;
>                 String username = cayenneUsername;
>                 String pwSource = cayennePasswordSource;
>                 String maxConnections = cayenneMaxConnections;
>                 String minConnections = cayenneMinConnections;
>
>                 String actualPassword = getPassword(pwSource);
>
>                 Module cayenneModule = binder ->
>
> ServerModule.contributeProperties(binder).put(Constants.JDBC_DRIVER_PR
> OPERTY, driver).put(Constants.JDBC_URL_PROPERTY, url)
>                           .put(Constants.JDBC_USERNAME_PROPERTY,
> username).put(Constants.JDBC_PASSWORD_PROPERTY, actualPassword)
>                           
> .put(Constants.JDBC_MIN_CONNECTIONS_PROPERTY,
> minConnections).put(Constants.JDBC_MAX_CONNECTIONS_PROPERTY,
> maxConnections);
>
>                 ServerRuntimeBuilder builder = ServerRuntime.builder();
>                 builder.addConfig("cayenne-testProject.xml");
>                 builder.addModule(cayenneModule);
>                 ServerRuntime createdRuntime = builder.build();
>
>                 try {
>                         // this will tell us on startup if it cannot 
> connect to the database
>                         createdRuntime.getDataSource().getConnection();
>                 } catch (SQLException e) {
>                         e.printStackTrace();
>                 }
>
>                 return createdRuntime;
>         }
>
>         private String getPassword(String passwordSourcePath) {
>                 try {
>                         return new
> String(Files.readAllBytes(Paths.get(passwordSourcePath)));
>                 } catch (IOException e) {
>                         return null;
>                 }
>         }
> }
>
> --End of code snippets--
> The primary advantage with this is that server admins can play around 
> with the database parameters and developers will not need to build 
> with a new cayenne xml, while still leaving the database password in 
> an external file.  Once each Spring profile has its default values, 
> then the server admins need only specify a parameter rather than 
> specifying all parameters.  We have somewhat regular datasource url changes for production
> which precipitated this refactor.   The code creating the ServerRuntime
> bean is intentionally verbose here to make it clearer in debugging 
> what values are getting passed through.  Obviously 
> application.properties would contain variables that are known to be 
> the same in different profiles, your situation may vary and some may 
> need to go in to application-PROFILE.properties or vice-versa.
>
> I hope that is useful to someone,
> Andrew
>
> -----Original Message-----
> From: Pascal Robert <pr...@druide.com>
> Sent: Friday, January 19, 2018 10:01 AM
> To: user@cayenne.apache.org
> Subject: Re: Redacting db user name and password from XML
>
> I confirm this behaviour, and I switched back to 
> XMLPoolingDataSourceFactory.
>
> > Le 18 janv. 2018 à 03:59, Andrus Adamchik <an...@objectstyle.org> a
> écrit :
> >
> > Ah, mystery solved. Looking at the code, more specifically to use
> properties for a given DataSource Cayenne would expect you to specify 
> at least DB URL and DB driver. Username/password are optional.
> >
> > Andrus
> >
> >
> >> On Jan 18, 2018, at 11:46 AM, Nikita Timofeev <
> ntimofeev@objectstyle.com> wrote:
> >>
> >> Hi all,
> >>
> >> Made some research, and here is what I've found.
> >>
> >> Cayenne do switch to System properties (defined via -D or with DI
> >> binding) automatically but it do so only when all properties are 
> >> defined.
> >>
> >> So this code will work as expected, and use overridden DataSource
> properties:
> >>
> >> ServerRuntime cayenneRuntime =
> >> ServerRuntime.builder().addConfig("cayenne-project.xml")
> >>       .addModule(binder -> ServerModule.contributeProperties(binder)
> >>               .put(Constants.JDBC_DRIVER_PROPERTY,
> "com.mysql.jdbc.Driver")
> >>               .put(Constants.JDBC_URL_PROPERTY,
> >> "jdbc:mysql://localhost:3306/test")
> >>               .put(Constants.JDBC_USERNAME_PROPERTY, "user")
> >>               .put(Constants.JDBC_PASSWORD_PROPERTY, "password"))
> >>       .build();
> >>
> >> While this will ignore password and use DataSource properties from XML:
> >>
> >> ServerRuntime cayenneRuntime =
> >> ServerRuntime.builder().addConfig("cayenne-project.xml")
> >>       .addModule(binder -> ServerModule.contributeProperties(binder)
> >>               .put(Constants.JDBC_PASSWORD_PROPERTY, "password"))
> >>       .build();
> >>
> >> I will add some information to logs, so at least it wouldn't be 
> >> surprising as it is now.
> >> But maybe we should change this to enable override of separate
> properties.
> >>
> >> On Thu, Jan 18, 2018 at 8:27 AM, Andrus Adamchik <
> andrus@objectstyle.org> wrote:
> >>>
> >>>
> >>>> On Jan 17, 2018, at 11:05 PM, Pascal Robert <pr...@druide.com>
> wrote:
> >>>>
> >>>> Ahhh… If I change the factory in the node definition to
> org.apache.cayenne.configuration.server.PropertyDataSourceFactory, it 
> does read the command-line properties.
> >>>
> >>> That should sorta happen automatically. We are still looking why 
> >>> it
> doesn't.
> >>>
> >>> Andrus
> >>>
> >>
> >>
> >>
> >> --
> >> Best regards,
> >> Nikita Timofeev
> >
>
>

Re: Redacting db user name and password from XML

Posted by John Huss <jo...@gmail.com>.
On Wed, Jul 18, 2018 at 1:26 PM Meeks, Andrew <an...@vt.edu> wrote:

> I feel as though a recent bit of code is closely related to the topic in
> this old thread.   The Cayenne <data-source> xml element supports a
> password with a path external to the application.  The observed environment
> properties appear to only include JDBC_PASSWORD_PROPERTY which seems to
> only support a literal password.  For Spring developers, an integration
> suggestion is included below.
>
> I would like to say, in agreement with the earlier thread, that the
> documentation at:
> https://cayenne.apache.org/docs/4.1/cayenne-guide/#appendix-a-configuration-properties
> is unclear in one respect.  I think it needs to state that all
> cayenne.jdbc.* properties must be defined in order for environment
> properties to override (or correctly override) the definition of
> data-source in the xml file.  That would have saved me a lot of stepping
> into code before I found what was happening in DelegatingDataSourceFactory.
> shouldConfigureDataSourceFromProperties(DataNodeDescriptor
> dataNodeDescriptor);
>

I believe only the URL and driver have to be specified via properties in
order for them to override the values in the cayenne project file. This is
still not really intuitive, but it's better than all of them being required.


>
> If you have a Spring Project and would like to control your <data-source>
> through a more spring-like configuration, here are relevant snippets from
> files of how I set it up based on examples in the cayenne documentation:
>
> -- file: application.properties --
> cayenne.jdbc.driver=oracle.jdbc.driver.OracleDriver
> cayenne.jdbc.max_connections=20
> cayenne.jdbc.min_connections=1
> cayenne.jdbc.username=SCOTT
>
> --file: application-dev.properties--
>
> cayenne.jdbc.passwordSource=C:\\home\\apps-config\\testProject\\cayenne_pw.txt
> cayenne.jdbc.url=jdbc:oracle:thin:@//localhost:1521/xe
>
> --file: application-prod.properties--
>
> cayenne.jdbc.passwordSource=C:\\home\\apps-config\\testProject\\cayenne_pw_prod.txt
> cayenne.jdbc.url=jdbc:oracle:thin:@//prod.db.example.com:1521/prod_svc
>
> --file: SpringMvcConfig.java--
> @Configuration
> public class MvcConfig extends WebMvcConfigurerAdapter {
>         @Value("${cayenne.jdbc.url}")
>         String cayenneClientUrl;
>
>         @Value("${cayenne.jdbc.driver}")
>         String cayenneDriverProperty;
>
>         @Value("${cayenne.jdbc.passwordSource}")
>         String cayennePasswordSource;
>
>         @Value("${cayenne.jdbc.username}")
>         String cayenneUsername;
>
>         @Value("${cayenne.jdbc.min_connections}")
>         String cayenneMinConnections;
>
>         @Value("${cayenne.jdbc.max_connections}")
>         String cayenneMaxConnections;
>
>         @Bean(name="serverRuntime")
>         public ServerRuntime serverRuntime(){
>
>                 String url = cayenneClientUrl;
>                 String driver = cayenneDriverProperty;
>                 String username = cayenneUsername;
>                 String pwSource = cayennePasswordSource;
>                 String maxConnections = cayenneMaxConnections;
>                 String minConnections = cayenneMinConnections;
>
>                 String actualPassword = getPassword(pwSource);
>
>                 Module cayenneModule = binder ->
>
> ServerModule.contributeProperties(binder).put(Constants.JDBC_DRIVER_PROPERTY,
> driver).put(Constants.JDBC_URL_PROPERTY, url)
>                           .put(Constants.JDBC_USERNAME_PROPERTY,
> username).put(Constants.JDBC_PASSWORD_PROPERTY, actualPassword)
>                           .put(Constants.JDBC_MIN_CONNECTIONS_PROPERTY,
> minConnections).put(Constants.JDBC_MAX_CONNECTIONS_PROPERTY,
> maxConnections);
>
>                 ServerRuntimeBuilder builder = ServerRuntime.builder();
>                 builder.addConfig("cayenne-testProject.xml");
>                 builder.addModule(cayenneModule);
>                 ServerRuntime createdRuntime = builder.build();
>
>                 try {
>                         // this will tell us on startup if it cannot
> connect to the database
>                         createdRuntime.getDataSource().getConnection();
>                 } catch (SQLException e) {
>                         e.printStackTrace();
>                 }
>
>                 return createdRuntime;
>         }
>
>         private String getPassword(String passwordSourcePath) {
>                 try {
>                         return new
> String(Files.readAllBytes(Paths.get(passwordSourcePath)));
>                 } catch (IOException e) {
>                         return null;
>                 }
>         }
> }
>
> --End of code snippets--
> The primary advantage with this is that server admins can play around with
> the database parameters and developers will not need to build with a new
> cayenne xml, while still leaving the database password in an external
> file.  Once each Spring profile has its default values, then the server
> admins need only specify a parameter rather than specifying all
> parameters.  We have somewhat regular datasource url changes for production
> which precipitated this refactor.   The code creating the ServerRuntime
> bean is intentionally verbose here to make it clearer in debugging what
> values are getting passed through.  Obviously application.properties would
> contain variables that are known to be the same in different profiles, your
> situation may vary and some may need to go in to
> application-PROFILE.properties or vice-versa.
>
> I hope that is useful to someone,
> Andrew
>
> -----Original Message-----
> From: Pascal Robert <pr...@druide.com>
> Sent: Friday, January 19, 2018 10:01 AM
> To: user@cayenne.apache.org
> Subject: Re: Redacting db user name and password from XML
>
> I confirm this behaviour, and I switched back to
> XMLPoolingDataSourceFactory.
>
> > Le 18 janv. 2018 à 03:59, Andrus Adamchik <an...@objectstyle.org> a
> écrit :
> >
> > Ah, mystery solved. Looking at the code, more specifically to use
> properties for a given DataSource Cayenne would expect you to specify at
> least DB URL and DB driver. Username/password are optional.
> >
> > Andrus
> >
> >
> >> On Jan 18, 2018, at 11:46 AM, Nikita Timofeev <
> ntimofeev@objectstyle.com> wrote:
> >>
> >> Hi all,
> >>
> >> Made some research, and here is what I've found.
> >>
> >> Cayenne do switch to System properties (defined via -D or with DI
> >> binding) automatically but it do so only when all properties are
> >> defined.
> >>
> >> So this code will work as expected, and use overridden DataSource
> properties:
> >>
> >> ServerRuntime cayenneRuntime =
> >> ServerRuntime.builder().addConfig("cayenne-project.xml")
> >>       .addModule(binder -> ServerModule.contributeProperties(binder)
> >>               .put(Constants.JDBC_DRIVER_PROPERTY,
> "com.mysql.jdbc.Driver")
> >>               .put(Constants.JDBC_URL_PROPERTY,
> >> "jdbc:mysql://localhost:3306/test")
> >>               .put(Constants.JDBC_USERNAME_PROPERTY, "user")
> >>               .put(Constants.JDBC_PASSWORD_PROPERTY, "password"))
> >>       .build();
> >>
> >> While this will ignore password and use DataSource properties from XML:
> >>
> >> ServerRuntime cayenneRuntime =
> >> ServerRuntime.builder().addConfig("cayenne-project.xml")
> >>       .addModule(binder -> ServerModule.contributeProperties(binder)
> >>               .put(Constants.JDBC_PASSWORD_PROPERTY, "password"))
> >>       .build();
> >>
> >> I will add some information to logs, so at least it wouldn't be
> >> surprising as it is now.
> >> But maybe we should change this to enable override of separate
> properties.
> >>
> >> On Thu, Jan 18, 2018 at 8:27 AM, Andrus Adamchik <
> andrus@objectstyle.org> wrote:
> >>>
> >>>
> >>>> On Jan 17, 2018, at 11:05 PM, Pascal Robert <pr...@druide.com>
> wrote:
> >>>>
> >>>> Ahhh… If I change the factory in the node definition to
> org.apache.cayenne.configuration.server.PropertyDataSourceFactory, it does
> read the command-line properties.
> >>>
> >>> That should sorta happen automatically. We are still looking why it
> doesn't.
> >>>
> >>> Andrus
> >>>
> >>
> >>
> >>
> >> --
> >> Best regards,
> >> Nikita Timofeev
> >
>
>

RE: Redacting db user name and password from XML

Posted by "Meeks, Andrew" <an...@vt.edu>.
I feel as though a recent bit of code is closely related to the topic in this old thread.   The Cayenne <data-source> xml element supports a password with a path external to the application.  The observed environment properties appear to only include JDBC_PASSWORD_PROPERTY which seems to only support a literal password.  For Spring developers, an integration suggestion is included below.  

I would like to say, in agreement with the earlier thread, that the documentation at: https://cayenne.apache.org/docs/4.1/cayenne-guide/#appendix-a-configuration-properties  is unclear in one respect.  I think it needs to state that all cayenne.jdbc.* properties must be defined in order for environment properties to override (or correctly override) the definition of data-source in the xml file.  That would have saved me a lot of stepping into code before I found what was happening in DelegatingDataSourceFactory. shouldConfigureDataSourceFromProperties(DataNodeDescriptor dataNodeDescriptor);

If you have a Spring Project and would like to control your <data-source> through a more spring-like configuration, here are relevant snippets from files of how I set it up based on examples in the cayenne documentation:

-- file: application.properties --
cayenne.jdbc.driver=oracle.jdbc.driver.OracleDriver
cayenne.jdbc.max_connections=20
cayenne.jdbc.min_connections=1
cayenne.jdbc.username=SCOTT

--file: application-dev.properties--
cayenne.jdbc.passwordSource=C:\\home\\apps-config\\testProject\\cayenne_pw.txt
cayenne.jdbc.url=jdbc:oracle:thin:@//localhost:1521/xe

--file: application-prod.properties--
cayenne.jdbc.passwordSource=C:\\home\\apps-config\\testProject\\cayenne_pw_prod.txt
cayenne.jdbc.url=jdbc:oracle:thin:@//prod.db.example.com:1521/prod_svc

--file: SpringMvcConfig.java--
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
	@Value("${cayenne.jdbc.url}")
	String cayenneClientUrl;
	
	@Value("${cayenne.jdbc.driver}")
	String cayenneDriverProperty;
	
	@Value("${cayenne.jdbc.passwordSource}")
	String cayennePasswordSource;

	@Value("${cayenne.jdbc.username}")
	String cayenneUsername;

	@Value("${cayenne.jdbc.min_connections}")
	String cayenneMinConnections;
	
	@Value("${cayenne.jdbc.max_connections}")
	String cayenneMaxConnections;

	@Bean(name="serverRuntime")
	public ServerRuntime serverRuntime(){
		
		String url = cayenneClientUrl;
		String driver = cayenneDriverProperty;
		String username = cayenneUsername;
		String pwSource = cayennePasswordSource;
		String maxConnections = cayenneMaxConnections;
		String minConnections = cayenneMinConnections;
		
		String actualPassword = getPassword(pwSource);
		
		Module cayenneModule = binder ->
			ServerModule.contributeProperties(binder).put(Constants.JDBC_DRIVER_PROPERTY, driver).put(Constants.JDBC_URL_PROPERTY, url)
			  .put(Constants.JDBC_USERNAME_PROPERTY, username).put(Constants.JDBC_PASSWORD_PROPERTY, actualPassword)
			  .put(Constants.JDBC_MIN_CONNECTIONS_PROPERTY, minConnections).put(Constants.JDBC_MAX_CONNECTIONS_PROPERTY, maxConnections);
		
		ServerRuntimeBuilder builder = ServerRuntime.builder();
		builder.addConfig("cayenne-testProject.xml"); 
		builder.addModule(cayenneModule);
		ServerRuntime createdRuntime = builder.build();
		
		try {
			// this will tell us on startup if it cannot connect to the database
			createdRuntime.getDataSource().getConnection();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return createdRuntime;
	}

	private String getPassword(String passwordSourcePath) {
		try {
			return new String(Files.readAllBytes(Paths.get(passwordSourcePath)));
		} catch (IOException e) {
			return null;
		}
	}
}

--End of code snippets--
The primary advantage with this is that server admins can play around with the database parameters and developers will not need to build with a new cayenne xml, while still leaving the database password in an external file.  Once each Spring profile has its default values, then the server admins need only specify a parameter rather than specifying all parameters.  We have somewhat regular datasource url changes for production which precipitated this refactor.   The code creating the ServerRuntime bean is intentionally verbose here to make it clearer in debugging what values are getting passed through.  Obviously application.properties would contain variables that are known to be the same in different profiles, your situation may vary and some may need to go in to application-PROFILE.properties or vice-versa.

I hope that is useful to someone,
Andrew

-----Original Message-----
From: Pascal Robert <pr...@druide.com> 
Sent: Friday, January 19, 2018 10:01 AM
To: user@cayenne.apache.org
Subject: Re: Redacting db user name and password from XML

I confirm this behaviour, and I switched back to XMLPoolingDataSourceFactory.

> Le 18 janv. 2018 à 03:59, Andrus Adamchik <an...@objectstyle.org> a écrit :
> 
> Ah, mystery solved. Looking at the code, more specifically to use properties for a given DataSource Cayenne would expect you to specify at least DB URL and DB driver. Username/password are optional.
> 
> Andrus
> 
> 
>> On Jan 18, 2018, at 11:46 AM, Nikita Timofeev <nt...@objectstyle.com> wrote:
>> 
>> Hi all,
>> 
>> Made some research, and here is what I've found.
>> 
>> Cayenne do switch to System properties (defined via -D or with DI
>> binding) automatically but it do so only when all properties are 
>> defined.
>> 
>> So this code will work as expected, and use overridden DataSource properties:
>> 
>> ServerRuntime cayenneRuntime =
>> ServerRuntime.builder().addConfig("cayenne-project.xml")
>>       .addModule(binder -> ServerModule.contributeProperties(binder)
>>               .put(Constants.JDBC_DRIVER_PROPERTY, "com.mysql.jdbc.Driver")
>>               .put(Constants.JDBC_URL_PROPERTY,
>> "jdbc:mysql://localhost:3306/test")
>>               .put(Constants.JDBC_USERNAME_PROPERTY, "user")
>>               .put(Constants.JDBC_PASSWORD_PROPERTY, "password"))
>>       .build();
>> 
>> While this will ignore password and use DataSource properties from XML:
>> 
>> ServerRuntime cayenneRuntime =
>> ServerRuntime.builder().addConfig("cayenne-project.xml")
>>       .addModule(binder -> ServerModule.contributeProperties(binder)
>>               .put(Constants.JDBC_PASSWORD_PROPERTY, "password"))
>>       .build();
>> 
>> I will add some information to logs, so at least it wouldn't be 
>> surprising as it is now.
>> But maybe we should change this to enable override of separate properties.
>> 
>> On Thu, Jan 18, 2018 at 8:27 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
>>> 
>>> 
>>>> On Jan 17, 2018, at 11:05 PM, Pascal Robert <pr...@druide.com> wrote:
>>>> 
>>>> Ahhh… If I change the factory in the node definition to org.apache.cayenne.configuration.server.PropertyDataSourceFactory, it does read the command-line properties.
>>> 
>>> That should sorta happen automatically. We are still looking why it doesn't.
>>> 
>>> Andrus
>>> 
>> 
>> 
>> 
>> --
>> Best regards,
>> Nikita Timofeev
> 


Re: Redacting db user name and password from XML

Posted by Pascal Robert <pr...@druide.com>.
I confirm this behaviour, and I switched back to XMLPoolingDataSourceFactory.

> Le 18 janv. 2018 à 03:59, Andrus Adamchik <an...@objectstyle.org> a écrit :
> 
> Ah, mystery solved. Looking at the code, more specifically to use properties for a given DataSource Cayenne would expect you to specify at least DB URL and DB driver. Username/password are optional.
> 
> Andrus
> 
> 
>> On Jan 18, 2018, at 11:46 AM, Nikita Timofeev <nt...@objectstyle.com> wrote:
>> 
>> Hi all,
>> 
>> Made some research, and here is what I've found.
>> 
>> Cayenne do switch to System properties (defined via -D or with DI
>> binding) automatically but it do so only when all properties are
>> defined.
>> 
>> So this code will work as expected, and use overridden DataSource properties:
>> 
>> ServerRuntime cayenneRuntime =
>> ServerRuntime.builder().addConfig("cayenne-project.xml")
>>       .addModule(binder -> ServerModule.contributeProperties(binder)
>>               .put(Constants.JDBC_DRIVER_PROPERTY, "com.mysql.jdbc.Driver")
>>               .put(Constants.JDBC_URL_PROPERTY,
>> "jdbc:mysql://localhost:3306/test")
>>               .put(Constants.JDBC_USERNAME_PROPERTY, "user")
>>               .put(Constants.JDBC_PASSWORD_PROPERTY, "password"))
>>       .build();
>> 
>> While this will ignore password and use DataSource properties from XML:
>> 
>> ServerRuntime cayenneRuntime =
>> ServerRuntime.builder().addConfig("cayenne-project.xml")
>>       .addModule(binder -> ServerModule.contributeProperties(binder)
>>               .put(Constants.JDBC_PASSWORD_PROPERTY, "password"))
>>       .build();
>> 
>> I will add some information to logs, so at least it wouldn't be
>> surprising as it is now.
>> But maybe we should change this to enable override of separate properties.
>> 
>> On Thu, Jan 18, 2018 at 8:27 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
>>> 
>>> 
>>>> On Jan 17, 2018, at 11:05 PM, Pascal Robert <pr...@druide.com> wrote:
>>>> 
>>>> Ahhh… If I change the factory in the node definition to org.apache.cayenne.configuration.server.PropertyDataSourceFactory, it does read the command-line properties.
>>> 
>>> That should sorta happen automatically. We are still looking why it doesn't.
>>> 
>>> Andrus
>>> 
>> 
>> 
>> 
>> -- 
>> Best regards,
>> Nikita Timofeev
> 


Re: Redacting db user name and password from XML

Posted by Andrus Adamchik <an...@objectstyle.org>.
Ah, mystery solved. Looking at the code, more specifically to use properties for a given DataSource Cayenne would expect you to specify at least DB URL and DB driver. Username/password are optional.

Andrus


> On Jan 18, 2018, at 11:46 AM, Nikita Timofeev <nt...@objectstyle.com> wrote:
> 
> Hi all,
> 
> Made some research, and here is what I've found.
> 
> Cayenne do switch to System properties (defined via -D or with DI
> binding) automatically but it do so only when all properties are
> defined.
> 
> So this code will work as expected, and use overridden DataSource properties:
> 
> ServerRuntime cayenneRuntime =
> ServerRuntime.builder().addConfig("cayenne-project.xml")
>        .addModule(binder -> ServerModule.contributeProperties(binder)
>                .put(Constants.JDBC_DRIVER_PROPERTY, "com.mysql.jdbc.Driver")
>                .put(Constants.JDBC_URL_PROPERTY,
> "jdbc:mysql://localhost:3306/test")
>                .put(Constants.JDBC_USERNAME_PROPERTY, "user")
>                .put(Constants.JDBC_PASSWORD_PROPERTY, "password"))
>        .build();
> 
> While this will ignore password and use DataSource properties from XML:
> 
> ServerRuntime cayenneRuntime =
> ServerRuntime.builder().addConfig("cayenne-project.xml")
>        .addModule(binder -> ServerModule.contributeProperties(binder)
>                .put(Constants.JDBC_PASSWORD_PROPERTY, "password"))
>        .build();
> 
> I will add some information to logs, so at least it wouldn't be
> surprising as it is now.
> But maybe we should change this to enable override of separate properties.
> 
> On Thu, Jan 18, 2018 at 8:27 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
>> 
>> 
>>> On Jan 17, 2018, at 11:05 PM, Pascal Robert <pr...@druide.com> wrote:
>>> 
>>> Ahhh… If I change the factory in the node definition to org.apache.cayenne.configuration.server.PropertyDataSourceFactory, it does read the command-line properties.
>> 
>> That should sorta happen automatically. We are still looking why it doesn't.
>> 
>> Andrus
>> 
> 
> 
> 
> -- 
> Best regards,
> Nikita Timofeev


Re: Redacting db user name and password from XML

Posted by Nikita Timofeev <nt...@objectstyle.com>.
Hi all,

Made some research, and here is what I've found.

Cayenne do switch to System properties (defined via -D or with DI
binding) automatically but it do so only when all properties are
defined.

So this code will work as expected, and use overridden DataSource properties:

ServerRuntime cayenneRuntime =
ServerRuntime.builder().addConfig("cayenne-project.xml")
        .addModule(binder -> ServerModule.contributeProperties(binder)
                .put(Constants.JDBC_DRIVER_PROPERTY, "com.mysql.jdbc.Driver")
                .put(Constants.JDBC_URL_PROPERTY,
"jdbc:mysql://localhost:3306/test")
                .put(Constants.JDBC_USERNAME_PROPERTY, "user")
                .put(Constants.JDBC_PASSWORD_PROPERTY, "password"))
        .build();

While this will ignore password and use DataSource properties from XML:

ServerRuntime cayenneRuntime =
ServerRuntime.builder().addConfig("cayenne-project.xml")
        .addModule(binder -> ServerModule.contributeProperties(binder)
                .put(Constants.JDBC_PASSWORD_PROPERTY, "password"))
        .build();

I will add some information to logs, so at least it wouldn't be
surprising as it is now.
But maybe we should change this to enable override of separate properties.

On Thu, Jan 18, 2018 at 8:27 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
>
>
>> On Jan 17, 2018, at 11:05 PM, Pascal Robert <pr...@druide.com> wrote:
>>
>> Ahhh… If I change the factory in the node definition to org.apache.cayenne.configuration.server.PropertyDataSourceFactory, it does read the command-line properties.
>
> That should sorta happen automatically. We are still looking why it doesn't.
>
> Andrus
>



-- 
Best regards,
Nikita Timofeev

Re: Redacting db user name and password from XML

Posted by Andrus Adamchik <an...@objectstyle.org>.

> On Jan 17, 2018, at 11:05 PM, Pascal Robert <pr...@druide.com> wrote:
> 
> Ahhh… If I change the factory in the node definition to org.apache.cayenne.configuration.server.PropertyDataSourceFactory, it does read the command-line properties.

That should sorta happen automatically. We are still looking why it doesn't.

Andrus


Re: Redacting db user name and password from XML

Posted by Pascal Robert <pr...@druide.com>.
Ahhh… If I change the factory in the node definition to org.apache.cayenne.configuration.server.PropertyDataSourceFactory, it does read the command-line properties.

> Le 17 janv. 2018 à 13:37, Mark Hull <ma...@gmail.com> a écrit :
> 
> Just to chime in on this topic, since my original question about user/password redaction I have done a lot of research and testing, and I decided to go with a modified version of Mike Kienenberger's DataSourceFactory. I also have a just plain Java application, btw. Since my needs were a bit different than his I streamlined the code a bit, and now I have a great resolution to my original quandary. By using the DataSourceFactory all implementation physical database properties are removed from the code (including the XML file),  the properties are provided at runtime, and the modeler still works great. I am including the code below in hopes that it may help you. Thanks to Mr. Kienenberger again for my ultimate solution. I note in passing that this method lets me change /which/ database I'm using at runtime as well, something I need to do but didn't mention earlier.
> 
> The DataSourceFactory class in the application is pretty simple. PurdahKeys is just a singleton POJO bean-like class:
> 
> public final class A1iciaDataSourceFactory implements DataSourceFactory {
> 
>     @Override
>     public DataSource getDataSource(DataNodeDescriptor nodeDescriptor) throws Exception {
>         MysqlConnectionPoolDataSource dataSource;
>         PurdahKeys purdah;
> 
>         purdah = PurdahKeys.getInstance();
>         dataSource = new MysqlConnectionPoolDataSource();
>         dataSource.setUser(purdah.getDatabaseUser());
>         dataSource.setPassword(purdah.getDatabasePassword());
>         dataSource.setServerName(purdah.getDatabaseServer());
>         dataSource.setPort(purdah.getDatabasePort());
>         dataSource.setDatabaseName(purdah.getDatabaseName());
>         dataSource.setUseSSL(purdah.getDatabaseUseSSL());
>         return dataSource;
>     }
> 
> }
> 
> The node definition in the XML file looks like:
> 
>     <node name="a1icia_datanode"
>          factory="com.hulles.a1icia.cayenne.A1iciaDataSourceFactory"
>  schema-update-strategy="org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy">
>         <map-ref name="a1icia_datamap"/>
>         <data-source>
>             <url value="announcement"/>
>         </data-source>
>      </node>
> 
> The <data-source> <url> property isn't really used anywhere in my code, but if I take it out I get an error from the modeler saying that there are no parameters, so I include it with a dummy value.
> 
> Again, I hope this helps someone. I should add that I'm using Cayenne 4.1 M1.
> 
> -- Mark Hull
> 
> 
> 
> On 01/16/2018 03:22 PM, Pascal Robert wrote:
>> Do -Dcayenne.jdbc.username really work? I’m trying to use that (so that the password is not stored in Git), and the runtime is still using the login information from the XML file.
>> 
>> Cayenne 4.1.M1.
>> ServerRuntime mysqlRuntime = ServerRuntime.builder().addConfig("cayenne-mysql.xml").build();
>> 
>>> Le 18 déc. 2017 à 11:49, Andrus Adamchik <an...@objectstyle.org> a écrit :
>>> 
>>> Hi Mark,
>>> 
>>> We've done quite a bit of work in Cayenne to avoid complex things like PasswordEncoding or custom DataSourceFactories. If all that is needed is to change / define login credentials, the simplest way is via properties [1]. [2] shows an example with a single DataNode. If you have more than one, you will need to add the project name and the DataNode name to the base property name. E.g.:
>>> 
>>> export MY_USER=user
>>> export MY_PASSWORD=secret
>>> 
>>> java -Dcayenne.jdbc.username.project.mynode=$MY_USER \
>>>     -Dcayenne.jdbc.password.project.mynode=$MY_PASSWORD \
>>>     -jar myapp.jar
>>> 
>>> 
>>> Hope this helps,
>>> Andrus
>>> 
>>> [1] http://cayenne.apache.org/docs/4.0/cayenne-guide/configuration-properties.html
>>> [2] https://stackoverflow.com/questions/45781378/best-practice-to-manage-apache-cayenne-project-xml-file
>>> 
>>> 
>>> 


Re: Redacting db user name and password from XML

Posted by Mark Hull <ma...@gmail.com>.
Just to chime in on this topic, since my original question about 
user/password redaction I have done a lot of research and testing, and I 
decided to go with a modified version of Mike Kienenberger's 
DataSourceFactory. I also have a just plain Java application, btw. Since 
my needs were a bit different than his I streamlined the code a bit, and 
now I have a great resolution to my original quandary. By using the 
DataSourceFactory all implementation physical database properties are 
removed from the code (including the XML file),  the properties are 
provided at runtime, and the modeler still works great. I am including 
the code below in hopes that it may help you. Thanks to Mr. Kienenberger 
again for my ultimate solution. I note in passing that this method lets 
me change /which/ database I'm using at runtime as well, something I 
need to do but didn't mention earlier.

The DataSourceFactory class in the application is pretty simple. 
PurdahKeys is just a singleton POJO bean-like class:

public final class A1iciaDataSourceFactory implements DataSourceFactory {

     @Override
     public DataSource getDataSource(DataNodeDescriptor nodeDescriptor) 
throws Exception {
         MysqlConnectionPoolDataSource dataSource;
         PurdahKeys purdah;

         purdah = PurdahKeys.getInstance();
         dataSource = new MysqlConnectionPoolDataSource();
         dataSource.setUser(purdah.getDatabaseUser());
         dataSource.setPassword(purdah.getDatabasePassword());
         dataSource.setServerName(purdah.getDatabaseServer());
         dataSource.setPort(purdah.getDatabasePort());
         dataSource.setDatabaseName(purdah.getDatabaseName());
         dataSource.setUseSSL(purdah.getDatabaseUseSSL());
         return dataSource;
     }

}

The node definition in the XML file looks like:

     <node name="a1icia_datanode"
          factory="com.hulles.a1icia.cayenne.A1iciaDataSourceFactory"
  schema-update-strategy="org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy">
         <map-ref name="a1icia_datamap"/>
         <data-source>
             <url value="announcement"/>
         </data-source>
      </node>

The <data-source> <url> property isn't really used anywhere in my code, 
but if I take it out I get an error from the modeler saying that there 
are no parameters, so I include it with a dummy value.

Again, I hope this helps someone. I should add that I'm using Cayenne 
4.1 M1.

-- Mark Hull



On 01/16/2018 03:22 PM, Pascal Robert wrote:
> Do -Dcayenne.jdbc.username really work? I’m trying to use that (so that the password is not stored in Git), and the runtime is still using the login information from the XML file.
>
> Cayenne 4.1.M1.
> ServerRuntime mysqlRuntime = ServerRuntime.builder().addConfig("cayenne-mysql.xml").build();
>
>> Le 18 déc. 2017 à 11:49, Andrus Adamchik <an...@objectstyle.org> a écrit :
>>
>> Hi Mark,
>>
>> We've done quite a bit of work in Cayenne to avoid complex things like PasswordEncoding or custom DataSourceFactories. If all that is needed is to change / define login credentials, the simplest way is via properties [1]. [2] shows an example with a single DataNode. If you have more than one, you will need to add the project name and the DataNode name to the base property name. E.g.:
>>
>> export MY_USER=user
>> export MY_PASSWORD=secret
>>
>> java -Dcayenne.jdbc.username.project.mynode=$MY_USER \
>>      -Dcayenne.jdbc.password.project.mynode=$MY_PASSWORD \
>>      -jar myapp.jar
>>
>>
>> Hope this helps,
>> Andrus
>>
>> [1] http://cayenne.apache.org/docs/4.0/cayenne-guide/configuration-properties.html
>> [2] https://stackoverflow.com/questions/45781378/best-practice-to-manage-apache-cayenne-project-xml-file
>>
>>
>>

Re: Redacting db user name and password from XML

Posted by Pascal Robert <pr...@druide.com>.
Do -Dcayenne.jdbc.username really work? I’m trying to use that (so that the password is not stored in Git), and the runtime is still using the login information from the XML file.

Cayenne 4.1.M1.
ServerRuntime mysqlRuntime = ServerRuntime.builder().addConfig("cayenne-mysql.xml").build();

> Le 18 déc. 2017 à 11:49, Andrus Adamchik <an...@objectstyle.org> a écrit :
> 
> Hi Mark,
> 
> We've done quite a bit of work in Cayenne to avoid complex things like PasswordEncoding or custom DataSourceFactories. If all that is needed is to change / define login credentials, the simplest way is via properties [1]. [2] shows an example with a single DataNode. If you have more than one, you will need to add the project name and the DataNode name to the base property name. E.g.:
> 
> export MY_USER=user
> export MY_PASSWORD=secret
> 
> java -Dcayenne.jdbc.username.project.mynode=$MY_USER \
>     -Dcayenne.jdbc.password.project.mynode=$MY_PASSWORD \
>     -jar myapp.jar 
> 
> 
> Hope this helps,
> Andrus
> 
> [1] http://cayenne.apache.org/docs/4.0/cayenne-guide/configuration-properties.html
> [2] https://stackoverflow.com/questions/45781378/best-practice-to-manage-apache-cayenne-project-xml-file
> 
> 
> 
>> On Dec 17, 2017, at 4:23 AM, Mark Hull <ma...@gmail.com> wrote:
>> 
>> I apologize if this question has been asked and answered before but: What is the best-practices solution to redact the database user name and password from an XML file created and used by Cayenne Modeler? The ServerRuntime build statement is simply:
>> 
>> cayenneRuntime = ServerRuntime.builder()
>> .addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
>>            .build();
>> 
>> It works just fine as long as the db user name and password are in the XML file, but I don't believe in leaving clear-text artifacts like that laying around in the code, so I want to add the user and password data at runtime from a Java method (not from an external file or an 'executable', whatever that means in the content of PasswordEncoding). Adding .user("xyz") and .password("zyx") to the build statement don't work, presumably because the DataNode is not the default and those statements just set their respective fields for the default DataNode.
>> 
>> If I have to, I can create either a Module to change those properties somehow at runtime (though the documentation for doing so is, to be kind, sparse), somehow implement the PasswordEncoding (even less documentation, because I don't know where it's used), or just edit the XML at runtime (horrible choice but looking like the best of a bad lot at this point).
>> 
>> All this seems like a lot of effort when I imagine this need must crop up fairly often among Cayenne users (it should, for security reasons IMO). Is there a simple standard way to do what I want? Or at least a standard way? I don't want to invent a new wheel here. I feel like I'm missing something obvious that everyone else knows about and that I just missed. Oh, by the way, whatever the solution is should still allow Cayenne Modeler to function normally.
>> 
>> I promise I searched for the answer everywhere I could think of. StackOverflow had a couple answers that used deprecated methods and didn't work when I tried them.
>> 
>> Thanks in advance for any help. I hope there's a really simple answer so I feel stupid but don't have to spend any more time on this than I have already. :)
>> 
>> - Mark Hull
>> 
>> /People say nothing is impossible, but I do nothing every day. - A. A. Milne/
> 


Re: Redacting db user name and password from XML

Posted by Andrus Adamchik <an...@objectstyle.org>.
Hi Mark,

We've done quite a bit of work in Cayenne to avoid complex things like PasswordEncoding or custom DataSourceFactories. If all that is needed is to change / define login credentials, the simplest way is via properties [1]. [2] shows an example with a single DataNode. If you have more than one, you will need to add the project name and the DataNode name to the base property name. E.g.:

export MY_USER=user
export MY_PASSWORD=secret

java -Dcayenne.jdbc.username.project.mynode=$MY_USER \
     -Dcayenne.jdbc.password.project.mynode=$MY_PASSWORD \
     -jar myapp.jar 


Hope this helps,
Andrus

[1] http://cayenne.apache.org/docs/4.0/cayenne-guide/configuration-properties.html
[2] https://stackoverflow.com/questions/45781378/best-practice-to-manage-apache-cayenne-project-xml-file



> On Dec 17, 2017, at 4:23 AM, Mark Hull <ma...@gmail.com> wrote:
> 
> I apologize if this question has been asked and answered before but: What is the best-practices solution to redact the database user name and password from an XML file created and used by Cayenne Modeler? The ServerRuntime build statement is simply:
> 
> cayenneRuntime = ServerRuntime.builder()
> .addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
>             .build();
> 
> It works just fine as long as the db user name and password are in the XML file, but I don't believe in leaving clear-text artifacts like that laying around in the code, so I want to add the user and password data at runtime from a Java method (not from an external file or an 'executable', whatever that means in the content of PasswordEncoding). Adding .user("xyz") and .password("zyx") to the build statement don't work, presumably because the DataNode is not the default and those statements just set their respective fields for the default DataNode.
> 
> If I have to, I can create either a Module to change those properties somehow at runtime (though the documentation for doing so is, to be kind, sparse), somehow implement the PasswordEncoding (even less documentation, because I don't know where it's used), or just edit the XML at runtime (horrible choice but looking like the best of a bad lot at this point).
> 
> All this seems like a lot of effort when I imagine this need must crop up fairly often among Cayenne users (it should, for security reasons IMO). Is there a simple standard way to do what I want? Or at least a standard way? I don't want to invent a new wheel here. I feel like I'm missing something obvious that everyone else knows about and that I just missed. Oh, by the way, whatever the solution is should still allow Cayenne Modeler to function normally.
> 
> I promise I searched for the answer everywhere I could think of. StackOverflow had a couple answers that used deprecated methods and didn't work when I tried them.
> 
> Thanks in advance for any help. I hope there's a really simple answer so I feel stupid but don't have to spend any more time on this than I have already. :)
> 
> - Mark Hull
> 
> /People say nothing is impossible, but I do nothing every day. - A. A. Milne/


Re: Redacting db user name and password from XML

Posted by Mark Hull <ma...@gmail.com>.
Thanks lots for responding. The application, or at least this part of 
the application, is a classic, plain old Java desktop application. I've 
used JNDI in the past with Tomcat as you say, and in ancient times I 
used raw JNDI and MySQL with a desktop application like the one I 
working on now. However, using JNDI here without a container like Tomcat 
would be non-trivial to implement, and I really want trivial. Raw JNDI 
gives me a migraine, and I don't think it's the right solution here. I 
just like so much that I can code a few lines, use the Cayenne Modeler 
to re-engineer my database, and I'm good to go -- except for the XML 
file, of course.

So yes, if you could guide me toward a different solution that would be 
wonderful.

If you're curious about the application, you can find it (in a very raw 
state, I'm in the process of moving things up to GitHub) at 
https://github.com/markhull/A1icia. A1iciaCayenne 
<https://github.com/markhull/A1icia/tree/master/A1icia%20Cayenne/src/com/hulles/a1icia/cayenne> 
is the module that happily feeds MySQL data objects to the rest of the 
application; it's packaged as a quasi-standalone JAR file, which is one 
of the reasons I don't want to add a lot of overhead to that part of the 
application. It also contains the XML file with the test database user 
name and password in it; I got tired of X'ing it out for each commit so 
I'll just change it later. :)

Thank you again,

Mark Hull


On 12/18/2017 06:51 AM, Michael Gentry wrote:
> Hi Mark,
>
> What type of application are you developing?  For web applications, which
> I'd imagine are the most common cases, using a JNDI DataSource is the way
> to go.  Your container (Tomcat, Jetty, etc) will provide database
> connection services to Cayenne through a JNDI lookup.  If you aren't
> developing a web application, we can guide you toward a different solution.
>
> Thanks,
>
> mrg
>
>
> On Sat, Dec 16, 2017 at 8:23 PM, Mark Hull <ma...@gmail.com> wrote:
>
>> I apologize if this question has been asked and answered before but: What
>> is the best-practices solution to redact the database user name and
>> password from an XML file created and used by Cayenne Modeler? The
>> ServerRuntime build statement is simply:
>>
>> cayenneRuntime = ServerRuntime.builder()
>> .addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
>>              .build();
>>
>> It works just fine as long as the db user name and password are in the XML
>> file, but I don't believe in leaving clear-text artifacts like that laying
>> around in the code, so I want to add the user and password data at runtime
>> from a Java method (not from an external file or an 'executable', whatever
>> that means in the content of PasswordEncoding). Adding .user("xyz") and
>> .password("zyx") to the build statement don't work, presumably because the
>> DataNode is not the default and those statements just set their respective
>> fields for the default DataNode.
>>
>> If I have to, I can create either a Module to change those properties
>> somehow at runtime (though the documentation for doing so is, to be kind,
>> sparse), somehow implement the PasswordEncoding (even less documentation,
>> because I don't know where it's used), or just edit the XML at runtime
>> (horrible choice but looking like the best of a bad lot at this point).
>>
>> All this seems like a lot of effort when I imagine this need must crop up
>> fairly often among Cayenne users (it should, for security reasons IMO). Is
>> there a simple standard way to do what I want? Or at least a standard way?
>> I don't want to invent a new wheel here. I feel like I'm missing something
>> obvious that everyone else knows about and that I just missed. Oh, by the
>> way, whatever the solution is should still allow Cayenne Modeler to
>> function normally.
>>
>> I promise I searched for the answer everywhere I could think of.
>> StackOverflow had a couple answers that used deprecated methods and didn't
>> work when I tried them.
>>
>> Thanks in advance for any help. I hope there's a really simple answer so I
>> feel stupid but don't have to spend any more time on this than I have
>> already. :)
>>
>> - Mark Hull
>>
>> /People say nothing is impossible, but I do nothing every day. - A. A.
>> Milne/
>>


Re: Redacting db user name and password from XML

Posted by Michael Gentry <bl...@gmail.com>.
Hi Mark,

What type of application are you developing?  For web applications, which
I'd imagine are the most common cases, using a JNDI DataSource is the way
to go.  Your container (Tomcat, Jetty, etc) will provide database
connection services to Cayenne through a JNDI lookup.  If you aren't
developing a web application, we can guide you toward a different solution.

Thanks,

mrg


On Sat, Dec 16, 2017 at 8:23 PM, Mark Hull <ma...@gmail.com> wrote:

> I apologize if this question has been asked and answered before but: What
> is the best-practices solution to redact the database user name and
> password from an XML file created and used by Cayenne Modeler? The
> ServerRuntime build statement is simply:
>
> cayenneRuntime = ServerRuntime.builder()
> .addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
>             .build();
>
> It works just fine as long as the db user name and password are in the XML
> file, but I don't believe in leaving clear-text artifacts like that laying
> around in the code, so I want to add the user and password data at runtime
> from a Java method (not from an external file or an 'executable', whatever
> that means in the content of PasswordEncoding). Adding .user("xyz") and
> .password("zyx") to the build statement don't work, presumably because the
> DataNode is not the default and those statements just set their respective
> fields for the default DataNode.
>
> If I have to, I can create either a Module to change those properties
> somehow at runtime (though the documentation for doing so is, to be kind,
> sparse), somehow implement the PasswordEncoding (even less documentation,
> because I don't know where it's used), or just edit the XML at runtime
> (horrible choice but looking like the best of a bad lot at this point).
>
> All this seems like a lot of effort when I imagine this need must crop up
> fairly often among Cayenne users (it should, for security reasons IMO). Is
> there a simple standard way to do what I want? Or at least a standard way?
> I don't want to invent a new wheel here. I feel like I'm missing something
> obvious that everyone else knows about and that I just missed. Oh, by the
> way, whatever the solution is should still allow Cayenne Modeler to
> function normally.
>
> I promise I searched for the answer everywhere I could think of.
> StackOverflow had a couple answers that used deprecated methods and didn't
> work when I tried them.
>
> Thanks in advance for any help. I hope there's a really simple answer so I
> feel stupid but don't have to spend any more time on this than I have
> already. :)
>
> - Mark Hull
>
> /People say nothing is impossible, but I do nothing every day. - A. A.
> Milne/
>

Re: Redacting db user name and password from XML

Posted by Mike Kienenberger <mk...@gmail.com>.
This is from my Cayenne 3.x project, but it's probably the same for 4.x.

Create your own DataSourceFactory class and use it to provide username
and password values.

==========================

public class ConfigFilePoolingDataSourceFactory implements DataSourceFactory {

    private static final Log logger =
LogFactory.getLog(ConfigFilePoolingDataSourceFactory.class);

    @Inject
    protected ResourceLocator resourceLocator;

    @Inject
    protected JdbcEventLogger jdbcEventLogger;

    public DataSource getDataSource(DataNodeDescriptor nodeDescriptor)
throws Exception {

        DataSourceInfo dataSourceDescriptor =
nodeDescriptor.getDataSourceDescriptor();


        if (dataSourceDescriptor == null) {
            String message = "Null dataSourceDescriptor for nodeDescriptor '"
                    + nodeDescriptor.getName()
                    + "'";
            logger.info(message);
            throw new ConfigurationException(message);
        }

        try {


            String name = dataSourceDescriptor.getDataSourceUrl();

            String jdbcDriver = getValueForKey(localConfigFile, name +
".dbDriver");
            String dataSourceUrl = getValueForKey(localConfigFile,
name + ".dbUrl");
            String userName = getValueForKey(localConfigFile, name +
".dbUserid");
            String password = getValueForKey(localConfigFile, name +
".dbPassword");
            String minConnectionsString =
getValueForKey(localConfigFile, name + ".minConnections");
            String maxConnectionsString =
getValueForKey(localConfigFile, name + ".maxConnections");
            int minConnections = Integer.parseInt(minConnectionsString);
            int maxConnections = Integer.parseInt(maxConnectionsString);

            // TODO: was PoolManager
            return new LoggingPoolManager(
                    jdbcDriver,
                    dataSourceUrl,
                    minConnections,
                    maxConnections,
                    userName,
                    password,
                    jdbcEventLogger);
        }
        catch (Exception e) {
            jdbcEventLogger.logConnectFailure(e);
            throw e;
        }
    }

====================================

then add it to your modeler node definition:

    <node name="AnnouncementsNode"
         adapter="org.apache.cayenne.dba.oracle.OracleAdapter"
         factory="com.xyz.cayenne.ConfigFilePoolingDataSourceFactory"
        >
        <map-ref name="Announcements"/>
        <data-source>
            <url value="announcement"/>
        </data-source>
    </node>


====================================


On Sat, Dec 16, 2017 at 8:23 PM, Mark Hull <ma...@gmail.com> wrote:
> I apologize if this question has been asked and answered before but: What is
> the best-practices solution to redact the database user name and password
> from an XML file created and used by Cayenne Modeler? The ServerRuntime
> build statement is simply:
>
> cayenneRuntime = ServerRuntime.builder()
> .addConfig("com/hulles/a1icia/cayenne/cayenne-a1icia.xml")
>             .build();
>
> It works just fine as long as the db user name and password are in the XML
> file, but I don't believe in leaving clear-text artifacts like that laying
> around in the code, so I want to add the user and password data at runtime
> from a Java method (not from an external file or an 'executable', whatever
> that means in the content of PasswordEncoding). Adding .user("xyz") and
> .password("zyx") to the build statement don't work, presumably because the
> DataNode is not the default and those statements just set their respective
> fields for the default DataNode.
>
> If I have to, I can create either a Module to change those properties
> somehow at runtime (though the documentation for doing so is, to be kind,
> sparse), somehow implement the PasswordEncoding (even less documentation,
> because I don't know where it's used), or just edit the XML at runtime
> (horrible choice but looking like the best of a bad lot at this point).
>
> All this seems like a lot of effort when I imagine this need must crop up
> fairly often among Cayenne users (it should, for security reasons IMO). Is
> there a simple standard way to do what I want? Or at least a standard way? I
> don't want to invent a new wheel here. I feel like I'm missing something
> obvious that everyone else knows about and that I just missed. Oh, by the
> way, whatever the solution is should still allow Cayenne Modeler to function
> normally.
>
> I promise I searched for the answer everywhere I could think of.
> StackOverflow had a couple answers that used deprecated methods and didn't
> work when I tried them.
>
> Thanks in advance for any help. I hope there's a really simple answer so I
> feel stupid but don't have to spend any more time on this than I have
> already. :)
>
> - Mark Hull
>
> /People say nothing is impossible, but I do nothing every day. - A. A.
> Milne/