I need a trusted plugin or a way to encrypt some texts in Grails Config file and the DB passwords in DataSource . as they are sensitive data , such as email username and password.
Is there a powerful and trustful way to do this
Not through a plugin, but it's possible to hide these sensitive config settings away in external files and then set appropriate file permissions on the external files so that they are only accessible to certain users.
Within Config.groovy, there is a setting for external configuration files:
grails.config.locations = [
"classpath:${appName}/externalDb.properties",
...
]
Within DataSource.groovy, a typical arrangement may be:
dataSource {
username = "yourUser"
password = "yourPassword"
...
}
Within your externalDb.properties (which would protected by your filesystem), you would then have the username/password/email/etc. overwritten:
dataSource.username = "prodUser"
dataSource.password = "secret1!"
You can leave the Config.groovy settings in-place and they will only be overwritten if the external config file is found. You could use this to your advantage by using the external files on prod and relying on the Config.groovy settings for your dev environments; you can also apply this logic to having different external config files per environment (we use JNDI at work but I think this built-in grails feature is even easier).
Here is how we had done it
we were defining the password in the Config.Groovy as follows
password = DESCodec.decode("String Returned by the output of encode")
class DESCodec {
def static encode = { String target ->
def cipher = getCipher(Cipher.ENCRYPT_MODE)
return cipher.doFinal(target.bytes).encodeBase64() as String
}
def static decode = { String target ->
def cipher = getCipher(Cipher.DECRYPT_MODE)
return new String(cipher.doFinal(target.decodeBase64())) as String
}
private static getCipher(mode) {
def keySpec = new DESKeySpec(getPassword())
def cipher = Cipher.getInstance("DES")
def keyFactory = SecretKeyFactory.getInstance("DES")
cipher.init(mode, keyFactory.generateSecret(keySpec))
return cipher
}
private static getPassword() {
"testsaltString".getBytes("UTF-8")
}
static void main(args) {
println args
if(args.length == 1) {
println encode(args[0])
} else {
println decode(args[1])
}
}
}
run from the command line
groovy DESCodec.groovy 'password'
to get the ciphertext for the a string, and use the cipher text in
the config files...
Related
I have a global library, which is normally loaded thusly:
#Library('pipelineUtilities')
def utils = new com.booty.jenkins.libraries.pipelineUtilities()
I have a folder library (in the vars directory), which looks like this:
#!groovy
class vars {
public static String gitAuthorization = "Basic TEzZmVGMH...lZMTNmZUYwZWU="
}
I hate hardcoding stuff like that, so I want to use a util function called getBasicAuth()
public String getBasicAuth(String account, String password){
String userPass = account + ":" + password
String basicAuth = "Basic "+ userPass.getBytes().encodeBase64()
return basicAuth
}
When I try to just use the #Library without actually using a library
#!groovy
#Library('pipelineUtilities')
class vars {
public static String gitAuthorization = "Basic TEzZmVGMH...lZMTNmZUYwZWU="
}
there is no problem, but nothing interesting really happens, of course, we just processed the #library annotation.
However:
#!groovy
#Library('pipelineUtilities')
def utils = new com.booty.jenkins.libraries.pipelineUtilities()
class vars {
private String serviceAccount = "xxxxyyyy"
private String serviceAccountPassword = "yyyyzzzzzz"
public String gitAuthorization = utils.getBasicAuth(serviceAccount, serviceAccountPassword)
}
does not pass the def utils = new com..... step, let alone call utils.getBasicAuth(). What it does is crash in some mysterious way.
So - 2 questions:
how do I put a try/catch block inside my code so i can see what went wrong in the #library section
How do I call a global library from within a folder library...
Alas, it is all so counter intuitive :-(
Thanks, .a.
So the problem is, I am not able to get the default value for controllerIP variable using the getControllerIP method without calling setControllerIP. I tried similar groovy code locally and it works, but not working on my jenkins server. Also tried lots of other combination in my groovy script but nothing worked.
Note that we are using Jenkins: pipeline shared groovy libraries plugin.
This is my pipeline job on Jenkins:
node{
def controllerParameters = new com.company.project.controller.DeploymentParameters() as Object
controllerParameters.setOSUsername('jenkins')
controllerParameters.setOSPassword('jenkins123')
controllerParameters.setBuildNumber(33)
//controllerParameters.setControllerIP('192.44.44.44')
//if I uncomment above line everything works fine but I need to get default value in a case
echo "I want the default value from other file"
controllerParameters.getControllerIP()
echo "my code hangs on above line"
}
This is my other file ../controller/DeploymentParameters.groovy
package com.company.project.controller
import groovy.transform.Field
def String osUsername
def String osPassword
#Field String controllerIP = "NotCreated" //tried few combinations
//Open Stack username
def String setOSUsername(String osUsername) {
this.osUsername = osUsername
}
def String getOSUsername() {
return this.osUsername
}
//Open Stack password
void setOSPassword(String osPassword) {
this.osPassword = osPassword
}
def String getOSPassword() {
return this.osPassword
}
//Open Stack floating ip of master vm
void setControllerIP(String controllerIP) {
this.controllerIP = controllerIP
}
def String getControllerIP() {
return this.controllerIP
}
When groovy executes lines like this.osUsername = osUsername or return this.osUsername it actually calls getters and setters instead of direct field access.
So this:
def String getOSPassword() {
return this.osPassword
}
behaves like this:
def String getOSPassword() {
return this.getOsPassword()
}
And you code enters infinite recursion (same for setter and assignment).
Within your setters and getters you need to use Groovy direct field access operator
def String getOSPassword() {
return this.#osPassword
}
How to get values from properties file please? and where should I put the file ?
Thank you
EDIT : I'm using grails 3.1.5 And I'm trying to get properties from a job class (quartz)
Either keep your properties directly in Config.groovy file.
Or you can create a .properties file to keep properties and add this file in Config.groovy
grails.config.locations = [ "classpath:grails-app-config.properties"]
and access it anywhere in application using
grailsApplication.config."propertyName"
We have a trait like this:
/**
* Load config from config locations given by property grails.config.locations.
* Based on http://grails.1312388.n4.nabble.com/Grails-3-External-config-td4658823.html
*/
trait ExternalConfigurationLoader implements EnvironmentAware {
#Override
void setEnvironment(Environment environment) {
loadExternalConfigLocations(environment)
}
void loadExternalConfigLocations(Environment environment) {
if (environment) {
def configLocations = findConfigLocationsFromApplicationGroovy()
DefaultResourceLocator resourceLocator = new DefaultResourceLocator()
for (String configLocation in configLocations) {
loadConfigLocation(configLocation, grails.util.Environment.current.name, environment, resourceLocator)
}
}
}
List<String> findConfigLocationsFromApplicationGroovy() {
def applicationGroovy = this.getClass().classLoader.getResource('application.groovy')
if (applicationGroovy) {
def applicationConfiguration = new ConfigSlurper(grails.util.Environment.current.name).parse(applicationGroovy)
return applicationConfiguration.grails.config.locations
}
[]
}
void loadConfigLocation(String configLocation, String currentEnvironmentName, Environment environment, ResourceLocator resourceLocator) {
def configurationResource = resourceLocator.findResourceForURI(configLocation)
if (configurationResource) {
log.debug "External config '$configLocation' found. Loading."
def configSlurper = new ConfigSlurper(currentEnvironmentName)
def config = configSlurper.parse(configurationResource.getURL())
environment.propertySources.addFirst(new MapPropertySource(configLocation, config))
} else {
log.debug "External config '$configLocation' not found."
}
}
}
Then we can add this trait to Application.groovy:
class Application extends GrailsAutoConfiguration implements ExternalConfigurationLoader {
and configure external config files in application.groovy:
grails.config.locations = ["classpath:myapp-config.groovy", "file:dev-config.groovy"]
If using Tomcat, you can then put myapp-config.groovy in Tomcats lib folder.
Note: this variant only supports external config files of type .groovy but you can extend it to support .yml or .properties if you prefer that. Also note that this example has some issues with overriding values from environment block in application.yml, so if you plan to override dataSource you will need to move the default configuration of dataSource from application.yml to application.groovy first.
There is also a plugin in the making that is adding similar support for grails.config.locations. See https://github.com/sbglasius/external-config
I am working on a small grails application. I would like to create a install wizard for the application giving the user the ability to configure data connection settings via a web interface. Is there a way to stall the data connection and configure the datasource while the application is running? I would like to do this while maintaining the ability to leverage GORM/Hibernate for all domain objects. Restarting/reloading the application after configuring the datasource would be ok.
In Config.groovy file add 1 more entry for value of grails.config.locations
in result you will have something like this
grails.config.locations = ["file:${userHome}/.grails/global-config.groovy",
"classpath:${appName}-config.properties",
"classpath:${appName}-config.groovy",
"file:${userHome}/.grails/${appName}-config.properties",
"file:${userHome}/.grails/${appName}-config.groovy",
"file:${userHome}/.grails/${appName}-MyDbconfig.groovy"]
In you application after user enters DB connection parameters write it to file
"file:${userHome}/.grails/${appName}-MyDbconfig.groovy"
in corresponding format. Like follwoing
dataSource{
url = '...'
username = '...'
password = '...'
properties {
...
}
}
save file and restart application.
Since you say the user should be able to configure the datasource via web interface then you should ask for configuration params since maxActive, maxIdle, etc... Once you have all the params you store anywhere you want.
Inside your Grails application:
// grails-app/conf/BootStrap.groovy
import utils.DataSourceConfigurator
class BootStrap {
def init = { servletContext ->
DataSourceConfigurator.configure(servletContext)
}
}
Like this you say to your application that once its ready to run it needs to configure the DataSource first.
package utils
import org.codehaus.groovy.grails.commons.ApplicationAttributes
import org.codehaus.groovy.grails.web.json.JSONObject
class DataSourceConfigurator {
private static JSONObject getDSConfig() {
JSONObject conf = new JSONObject()
// Go find the configuration wherever you stored it from the web interface, parse it and return it.
return conf
}
public static final configure = { servletContext ->
if(!servletContext) {
// Invalid servlet context
return
}
def context = servletContext.getAttribute(ApplicationAttributes.APPLICATION_CONTEXT)
def ds = context?.dataSourceUnproxied
if(!ds) {
// There is no datasource available to configure.
return
}
JSONObject config = getDSConfig()
if(!config) {
// No previous configuration saved from web interface.
return
}
ds.setInitialSize(config.initialSize)
ds.setMaxWait(config.maxWait)
ds.setMaxActive(config.maxActive)
ds.setMinIdle(config.minIdle)
ds.setMaxIdle(config.maxIdle)
....
// There are many other variables to configure. Check them by yourself.
}
}
For more information you could check the documentation regarding DataSource configuration: http://docs.grails.org/latest/guide/conf.html#transactionAwareDataSourceProxy
I just wanted to know that is it possible to set the value of a variable in Grails controller from the configuration file like config.groovy or some other configuration file?
For instance , my controller is as follows:
class WebsiteController {
def show(){
String user_name = "value to be fetched from configuration file"
}
}
Here, I want to set the value of user_name from the configuration file. I have no idea how to do this.
I have been given this requirement by my senior. I searched online but couldn't find anything relevant. If it is possible, please tell me the approach.
Thanks
Here is an example of properties added to the Config.groovy:
environments {
development {
tipline.email.address="joe#foo.us"
grails.logging.jul.usebridge = true
}
staging {
tipline.email.address="mailinglist#foo.us"
grails.logging.jul.usebridge = true
}
production {
tipline.email.address="mailinglist#foo.us"
grails.logging.jul.usebridge = false
// TODO: grails.serverURL = "http://www.changeme.com"
}
}
To access them in your code:
println("Email :"+grailsApplication.config.tipline.email.address)
Properties are properties =)
Properties properties = new Properties()
File propertiesFile = new File('test.properties')
propertiesFile.withInputStream {
properties.load(it)
}
def runtimeString = 'a'
assert properties."$runtimeString" == '1'
assert properties.b == '2'
Taken from Get values from properties file using Groovy
Another possibility is to inject parameters into the controller by using a property override configuration:
// Config.groovy:
website.user = "me"
beans {
'<replace by package>.WebsiteController' {
userName = website.user
}
}
// Controller:
class WebsiteController {
String userName
def show(){
//.. use userName ..
}
}
In this case you don't need grailsApplication and you don't hard code the configuration path in the Controller. Less dependencies make testing easier. :)