grails external configuration values are not read - grails

I want to use external configuration in my application. Along with it I use mail plugin and want to store its configuration in external .property file. I've chaged my Config.groovy so now it looks for external configuration under USER_HOME/.grails/APP_NAME-configuration.properties:
environments {
development {
grails.logging.jul.usebridge = true
if (new File("${userHome}/.grails/${appName}-config.properties").exists()) {
println "*** User defined config ***"
grails.config.locations = ["file:${userHome}/.grails/${appName}-config.properties"]
}
}
.....
}
As you can see there is if statement which tests is the configuration file exists. It exists so every time I see "* User defined config *" message when application starts.
I'm running application in development mode. After that configuration of my mail plugin goes:
grails {
mail {
host = grailsApplication.config['mail']['host']
port = grailsApplication.config['mail']['host']
username = grailsApplication.config['mail']['username']
password = grailsApplication.config['mail']['password']
props = ["mail.smtp.auth": "true",
"mail.smtp.socketFactory.port": "465",
"mail.smtp.socketFactory.class": "javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback": "false"]
}
}
When I tried to send a message with email plugin it appeared that configuration of email plugin is not initialized - username, password = null and host, port have default values (localhost and -1). So it seemed to me that config.properties file is simply not loaded. I decided to check if config.properties had been loaded and found out that grailsApplication.config object contained all properties that I'd defined in config.properties: mail.host, mail.port, mail.username, mail.password. I checked if it's possible to get corresponding properties using grailsApplication.config['property']['name'] expression (in debug mode). This expression gave proper values for all mail.host, mail.port, mail.username and mail.password. I also tried to use just grailsApplication.config['property.name'] (with one pair of brackets and '.') but this variant didn't work.
Can someone help me handle this situation? I've spent almost 3 trying different variants and still don't have a solution. Thank you.

You cannot load maps from .properties file. You should use .groovy file instead of .properties.
You can load configuration from external *.groovy file where you can have maps etc. create a file with contents below...
grails {
mail {
host = smtp.gmail.com
port = 465
username = username
password = password
props = ["mail.smtp.auth" : "true",
"mail.smtp.socketFactory.port" : "465",
"mail.smtp.socketFactory.class" : "javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback": "false"]
}
}
And use this in your config.groovy,
grails.config.locations = ["classpath:mail-config.groovy"]

Related

Service Principal Creation by Terraform doesn't provide password/secret in the output

when generating Service Principal in Azure manually, as a result of the operation I'm provided a password.
It's not the case however if I create service principal with Terraform, the password is not among the outputs of this module:
+ azuread_service_principal.k8s_principal
id: <computed>
application_id: "${azuread_application.app.application_id}"
display_name: <computed>
Is there anything I missed? Why does the Terraform behavior differs in the output compared to CLI?
password is required INPUT to the azuread_service_principal_password block. As such, you can generate a random password and export it yourself. Complete Terraform code is something like this:
resource "azuread_application" "app" {
name = "${local.application_name}"
}
# Create Service Principal
resource "azuread_service_principal" "app" {
application_id = "${azuread_application.app.application_id}"
}
resource "random_string" "password" {
length = 32
special = true
}
# Create Service Principal password
resource "azuread_service_principal_password" "app" {
end_date = "2299-12-30T23:00:00Z" # Forever
service_principal_id = "${azuread_service_principal.app.id}"
value = "${random_string.password.result}"
}
output "sp_password" {
value = "${azuread_service_principal_password.app.value}"
sensitive = true
}
to who using newer version of Terraform, you don't need to preset the password, following code is working fine:
resource "azuread_service_principal_password" "auth_pwd" {
service_principal_id = azuread_service_principal.auth.id
}
output "auth_client_secret" {
value = azuread_service_principal_password.auth_pwd.value
description = "output password"
sensitive = true
}
then you can run the following cli to retrieve the password:
terraform output -raw auth_client_secret
tested on terraform 1.0.10, hashicorp/azuread provider 2.11
In the terraform document, the azuread_service_principal block only defines the Argument application_id and Attributes id, display_name, So you only could see these resources. Also, the azuread_service_principal_password block allows you to export the Key ID for the Service Principal Password. You still could not see the real password.
In the Azure CLI az ad sp create-for-rbac has an optional parameter --Password. So you could see the password output.

Setting GOOGLE_APPLICATION_CREDENTIALS for an MVC site hosted on azure

Title says it all pretty much.
I tried uploading the json file to azure storage and referenced it's url when setting the GOOGLE_APPLICATION_CREDENTIALS environment variable under app settings, but when remotely debugging the site, apparently the url/directory was not in an acceptable format. I can’t store the json file locally either because the website doesn’t have any idea about my C drive directories.
Where should I store this file so that I can set the GOOGLE_APPLICATION_CREDENTIALS environment variable for my azure site to the directory of the json file?
The ToChannelCredentials() approach does not seem to work anymore, so I come up with an other solution that works on Azure. I create a text file in the /bin folder of my Azure server with the credentials and then I point the environment variable to this file. Google Cloud API will use this for the default credentials.
string json = #"{
'type': 'service_account',
'project_id': 'xxx',
'private_key_id': 'xx',
'private_key': 'xxx',
...
}"; // this is the content of the json-credentials file from Google
// Create text file in projects bin-folder
var binDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().CodeBase);
string fullPath = Path.Combine(binDirectory, "credentials.json").Replace("file:\\","");
using (StreamWriter outputFile = new StreamWriter(fullPath, false)) {
outputFile.WriteLine(json);
}
// Set environment variabel to the full file path
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", fullPath);
// Now you can call the service and it will pick up your credentials
TranslationServiceClient client = TranslationServiceClient.Create();
If anyone is wondering how to handle the Google's credentials smoothly in .Net applications instead of strange way of using the file on server, this is how I solved it for Translation Service. Other services must follow same principle:
store the content of the Google credentials json file as an environment variable in settings.json/azure configuration for your app (using ' ' instead of " " for inner text):
"GOOGLE_APPLICATION_CREDENTIALS": "{'type': 'service_account','project_id': ...}"
create and return the client:
var credential = GoogleCredential.FromJson(Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS"));
var channelCredentials = credential.ToChannelCredentials();
var channel = new Channel(TranslationServiceClient.DefaultEndpoint.ToString(), channelCredentials);
return TranslationServiceClient.Create(channel);
Took a while for me to figure it our. Hope it helps.
I use the .json file in my local environment (because of environment variable length limit in Windows) and on Azure I use an "Application setting" to set an environment variable. This code handles both cases:
string? json;
var filename = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS");
if (filename != null)
{
json = System.IO.File.ReadAllText(filename);
}
else
{
json = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS_STRING");
if (json == null)
{
throw new Exception(
"GOOGLE_APPLICATION_CREDENTIALS_STRING environment variable with JSON is not set");
}
}
var credential = GoogleCredential.FromJson(json).ToChannelCredentials();
var grpcChannel = new Channel("firestore.googleapis.com", credential);
var grcpClient = new Firestore.FirestoreClient(grpcChannel);
var firestoreClient = new FirestoreClientImpl(grcpClient, FirestoreSettings.GetDefault());
return await FirestoreDb.CreateAsync(FirebaseProjectId, firestoreClient);
Was looking how to set the "GOOGLE_APPLICATION_CREDENTIALS" in Azure App Service. The answers here didn't help me. My solution is very simple without any code change.
In the configuration of the app service go to the Path Mappings
Add a New Azure Storage Mount. eg /mounts/config
Add the credentials.json file to the file share
In the application settings, add the GOOGLE_APPLICATION_CREDENTIALS and set the value to: /mounts/config/credentials.json
That is all.
In the azure app on the azure portal go to application settings and add the credentials under application settings tab
Then you can reference them in your code as they were in your web.config file.

Contao: How can I change the protocol of the base url?

In Contao 3.5.9
I have uploaded to new server and am using a different domain from the original installation. I am also using https://
Many of the resources needed are not being loaded because the system has the base url set to http://
It is using the correct domain name in the base url, but the wrong protocol.
I cannot login to the admin.
I searched Google (not much there about Contao) and found this: http://blog.qzminski.com/article/move-the-contao-to-another-server.html
reading it, it seems that the base url is set in the admin, which means it can be found somewhere in the db.
I have search the DB dump but cannot find it.
How can I change the protocol of the base url?
Contao uses the following to determine whether the current request is done via SSL or not » \Environment::get('ssl'):
/**
* Return true if the current page was requested via an SSL connection
*
* #return boolean True if SSL is enabled
*/
protected static function ssl()
{
return ($_SERVER['SSL_SESSION_ID'] || $_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1);
}
It is possible that your server environment does not set either of these $_SERVER globals. This can be the case if you are using an SSL proxy for example.
If that is the case for you, then you can extend the SSL detection by inserting
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'])
{
$_SERVER['HTTPS'] = 1;
}
into your /system/config/initconfig.php. See https://github.com/contao/core/issues/7542 for example (only German though).

f5 LTM irule - can a pool name be generated in an irule

I need to setup a configuration for many similar environments. Each will have a different hostname that follows a pattern, e.g. env1, env2, etc.
I can use a pool per environment and a single virtual server with an irule that selects a pool based on hostname.
What I'd prefer to do is dynamically generate and select the pool name based on the requested hostname rather than listing out every pool in the switch statement. It's easier to maintain and automatically handles new environments.
The code might look like:
when HTTP_REQUEST {
pool [string tolower [HTTP:host]]
}
and each pool name matches the hostname.
Is this possible? Or is there a better method?
EDIT
I've expanded my hostname pool selection. I'm now trying to include the port number. The new rule looks like:
when HTTP_REQUEST {
set lb_port "[LB::server port]"
set hostname "[string tolower [getfield [HTTP::host] : 1]]"
log local0.info "Pool name $hostname-$lb_port-pool"
pool "$hostname-$lb_port-pool"
}
This is working, but I'm seeing no-such-pool errors in the logs because somehow a port 0 request is coming into the pool. It seems to be the first request and the followed by the request with the legitimate port.
Wed Feb 17 20:39:14 EST 2016 info tmm tmm[6519] Rule /Common/one-auto-pool-select-by-hostname-port <HTTP_REQUEST>: Pool name my.example.com-80-pool
Wed Feb 17 20:39:14 EST 2016 err tmm1 tmm[6519] 01220001 TCL error: /Common/one-auto-pool-select-by-hostname-port <HTTP_REQUEST> - no such pool: my.example.com-0-pool (line 1) invoked from within "pool "$hostname-$lb_port-pool""
Wed Feb 17 20:39:14 EST 2016 info tmm1 tmm[6519] Rule /Common/one-auto-pool-select-by-hostname-port <HTTP_REQUEST>: Pool name my.example.com-0-pool
What is causing the port 0 request? And is there any workaround? e.g. could I test for port 0 and select a default port or ignore it?
ONE MORE EDIT
Rebuilt the virtual server, and now the error has gone. The rebuild of the VS was just to rename it though. I'm fairly sure I recreated the settings exactly the same.
Yes, you can specify the pool name in a string. What you have there would work as long as you have a pool with that same name. Though it doesn't show an example of doing it this way, you can also check out the pool wiki page on DevCentral for more information.
As an aside, in my environment I generally create pools with the suffix _pool to distinguish them from other objects when looking at config files. So in my iRules, I would do something like this (essentially the same thing):
when HTTP_REQUEST {
pool "[string tolower [HTTP::host]]_pool"
}
The simple case mentioned by Michael works. I'd recommend removing the port value if present:
when HTTP_REQUEST {
pool "pool_[string tolower [getfield [HTTP::host] : 1]]_[LB::server port]"
}
Keep in mind that clients might send a partial hostname. If the DNS search path is set to example.org then the client might hit shared/ which maps to shared.example.org, but the HTTP::host header will just have shared. Some API libraries may append the port number even if it's on the default port. Simple code might not send a Host header. Malicious code might send completely bogus Host headers. You could trap these cases with catch.
You can also use a datagroup to map hostnames to pools. This allows multiple hosts to use the same pool. Sample code:
when HTTP_REQUEST {
set host [string tolower [getfield [HTTP::host] ":" 1]]
if { $host == "" } {
# if there's no Host header, pull from virtual server name
# we use: pool_<virtualserver>_PROTOCOL
set host [getfield [virtual name] _ 2]
} elseif { not ($host contains ".") } {
# if Host header does not contain a dot, assume example.org
set host $host.example.org
}
set pool [class match -value $host[HTTP::uri] starts_with dg_shared.example.org]
if { $pool ne ""} {
set matched [class match -name $host[HTTP::uri] starts_with dg_shared.example.org]
set log(matched) $matched
set log(pool) $pool
if { [catch { pool $pool } ] } {
set log(reason) "Failed to Connect to Pool"
call hsllog log
call errorpage 404 $log(reason) "https://[HTTP::host][HTTP::uri]" log
}
} else {
call errorpage 404 "No Pool Found" "https://[HTTP::host][HTTP::uri]" log
}
}
when SERVER_CONNECTED {
if {!($pool ends_with "_HTTPS") } {
SSL::disable serverside
}
}
This allows host.example.org/path1 to be on a different pool than host.example.org or host.example.org/path2 by including separate entries in the datagroup. I didn't include the hsllog and errorpage procs here. They dump the log array as well as the other passed parameters.
We then disable serverside ssl for pools that don't end in _HTTPS.
Note: As with dynamically generated pool names, the BIG-IP UI does not look inside datagroups for pool references, so the interface will allow you do delete one of these pools thinking it's not in use.
We use BigIPReport to identify orphan pools:
https://devcentral.f5.com/s/articles/bigip-report

trouble viewing h2 db used in grails project

I'm trying to have a look at the tables generated in h2 db used in Grails project, but something's amiss.
I connect to the browser console at http://127.0.1.1:8082/ but all that's there to browse is INFORMATION_SCHEMA and Users. How do I get tho the tables used/generated by the app?
Just started building out the app and only few domain classes are in place and I'm trying to get a feel for working h2. Prior to that I've been using PostgreSql in all projects so this is very unnerving for the moment.
Thanks in advance
Are you using the right JDBC URL when logging in?
The default in grails is jdbc:h2:mem:devDB.
When an non-existing URL is given, like jdbc:h2:blabla, an empty database is created, with the default INFORMATION_SCHEMA and Users as you described.
Make sure you connect to the URL where your grails application stores its tables. You can find the URL in $GRAILS_PROJECT/config/DataSource.groovy, after the url definition.
environments {
development {
dataSource {
pooled = false
logSql = false
username = "sa"
password = ""
dialect = "com.hp.opr.hibernate.dialect.H2Dialect"
driverClassName = "org.h2.Driver"
dbCreate = "create-drop"
url = "jdbc:h2:mem:devDB;DB_CLOSE_DELAY=-1;MVCC=TRUE"
}
}
}
If you're using 2.0 the web console is enabled by default in dev mode and can be enabled in other environments: http://grails.org/doc/2.0.0.M2/guide/conf.html#databaseConsole
If you're not using 2.0 yet you can install the http://grails.org/plugin/dbconsole plugin or follow the link to my blog post and set it up yourself if you want to customize the url (or if you're using Grails pre-1.3.6 since the plugin has an artificial version restriction to 1.3.6+)
... so in datasource I changed the url to: url = "jdbc:h2:rswDb" (removing the 'mem' part and changing the name of the db). Then 3 db files showed up in the root dir of the project.
Next, in db console set the jdbc url to: jdbc url: jdbc:h2:~/work/web/rsw/rswDb
... and when I hit 'connect' all the tables were there!
Thanks again!

Resources