Hi everyone Can someone explain why Lucee enforc...
# lucee
c
Hi everyone Can someone explain why Lucee enforces the use of a password to use certain cache functions, like:
Copy code
CacheRegionNew()
ACF does not enforce this. The consequences are enormous for migration projects. I am now facing this exact issue. We are migrating from ACF to Lucee, and from what I can see, unless we expose the plain text:
Copy code
this.webAdminPassword
In the:
Copy code
Application.cfc
We would need to build a form, before the main application loads and ask the user to submit the Administrator password, before proceeding. As I understand, the Administrator password is an encrypted hash, which means it cannot be reversed. So, I would need expose the clear text version of the password? I mean I understand that it is a security issue, but why does ACF feel that it is unnecessary to enforce this methodology? 🤔
To be honest, it would be slightly better, if Lucee allowed the hash version of the password, to be used as:
Copy code
this.webAdminPassword
At least, we could read this out of a file or just expose it directly. But, if a malicious user got hold of the hash, it still wouldn’t allow them to get into the Administrator UI.
z
can't you define it in application.cfc as the docs suggest? https://docs.lucee.org/reference/functions/cacheregionnew.html
👍 1
c
Hi Zacster Yes. Absolutely, and this would be the easiest option, by far. But, is it OK to expose a cleartext Administrator password in the
Application.cfc
? I mean maybe, it is OK? But, it doesn't feel OK?
In the past, when I transfer passwords into the
Application.cfc
, I read sensitive directly from the database. Normally, a password in the DB, would either be an encrypted Hash or just encrypted? Clearly, the latter would be reversible and so would be a good candidate to resolve this problem. But, it may not be possible to store the Administrator password in the DB, due to company security policies. By the way, I am working, as a contractor, for another company, so I don't know yet, whether they would allow this approach. But, my main question, is why do the guys at Lucee feel that certain cache functions, like:
Copy code
CacheRegionNew()
Require an Administrator password to work? When ACF doesn't require an Administrator password?
c
To keep the password value out of your code, you can define it as an environment variable in your OS and then reference it in Lucee using
server.system.environment.MYWEBCONTEXTPASSWORD
(or however you want to name it)
👍 1
c
Thanks very much. This sounds like a better approach 🙏 Do I create these environment variables inside Lucee Administrator or are you talking about a Windows environmental variable, which I can set like: https://docs.oracle.com/en/database/oracle/machine-learning/oml4r/1.5.1/oread/creating-and-modifying-environment-variables-on-windows.html I never knew I could access stuff like this via:
Copy code
server.system.environment
Awesome advice. 🙌 Currently, I have added the password like this: webroot/settings.json
Copy code
{
    "adminSalt":"294AFCA2-7E60-4721-8636FA62CB4F1705",
    "hspw":"b37158b3b23fc83851d9f3a3ba6d9241b7490b4ffc468d8d7c8ce01ff987cf76",
}
And then decrypt in
Application.cfc
I cannot use the CommandBox
.cfconfig.json
values as the password here is an encrypted hash, which cannot be reversed. However, I like your idea, so I might add it, into an environmental variable as an encrypted value, along with its salt.
z
you can just define the cache in application.cfc, you don't need the admin password
👍 1
for security reasons any context wide changes require a password, but you can just defined the cache for your application
👍 1
c
Is
Copy code
CacheRegionNew()
The only cache method that requires a password in Lucee?
To be honest. I am not sure I can define the cache in the
application.cfc
, for many reasons. It seems the the cache is created dynamically based on a chain of different actions. When you say:
for security reasons any context wide changes require a password, but you can just defined the cache for your application
How do I define the cache in a Lucee application without a password? I would be extremely grateful for a description of how to carry this out. 🙏
c
Hi Zackster I have been trying to implement a Lucee cache, using the
Application.cfc
initialisation methodology When I use: Application.cfc
Copy code
variables.szCacheName = "CONFIGSETTINGS";
variables.szApplicationName = "LA-EPORTFOLIO";
variables.szPropertiesCachename = ucase(variables.szApplicationName) & "_" & ucase(variables.szCacheName);
variables.stuCacheProps = {
    CLEARONFLUSH = "true",
    DISKPERSISTENT = "true",
    ETERNAL = "true",
    MAXELEMENTSINMEMORY = "1000000",
    MAXELEMENTSONDISK = "0",
    OBJECTTYPE = "OBJECT",
    OVERFLOWTODISK = "true",
    STATISTICS = "true",
    TIMETOLIVESECONDS = 0,
    TIMETOIDLESECONDS = 0
};

this.cache.connections[variables.szPropertiesCachename] = {
    class: 'lucee.runtime.cache.ram.RamCache',
    custom: variables.stuCacheProps,
    default: 'object'
};
And I do: Application.cfc
Copy code
<cffunction name="cacheNames" access="public" output="false" returnType="array">
    <cfreturn getPageContext().getConfig().getCacheConnections().keySet().toArray() />
</cffunction>

<cffunction name="onRequestStart" access="public" output="false" returnType="boolean">
    <cfargument name="targetPage" type="string" required="true" />

    <cfscript>
        variables.cacheNamesJava = this.cacheNames();
        variables.cacheNames = [].append(variables.cacheNamesJava, true)
        WriteDump(var={
            cacheNamesProperties = CacheGetProperties(type=variables.cacheNames[1]),
			cacheNames = variables.cacheNames
        },output="C:\domains\acf-lucee-   shared\logs\la_code_application_onRequestStart_160122.htm",format="html");
    </cfscript>
...
I get the following output [please see screenshot] I just don't fee that the cache has initialise properly. Where are all the custom props and the name? Do I have to install ramCache?
z
ram cache is built in?
👍 1
first question, does it actually work?
c
la_code_application_onRequestStart_160122-htm (1).png
Hmmm. I am not sure if it works or not. The properties look incomplete?
To be honest, I have never worked with cache. I have only ever created custom cache stuff, using the application scope?
Why isn't the name in the cacheNamesProperties struct? I would expect this struct to, at least, contain:
Copy code
name: la-eportfolio_configsettings
z
simple to test, do a cachePut, then cacheIdExists, or cacheGet etc to confirm?
👍 1
c
OK. I will give it a go...
OK. I guess I make up the ID? Anyway, this works:
Copy code
variables.cacheNamesJava = this.cacheNames();
        variables.cacheNames = [].append(variables.cacheNamesJava, true)
        WriteDump(var={
            cacheNamesProperties = CacheGetProperties(type=variables.cacheNames[1]),
            cacheNames = variables.cacheNames
        },output="C:\domains\acf-lucee-shared\logs\la_code_application_onRequestStart_160122.htm",format="html");
        variables.cacheput_obj = now();
        cachePut('cacheput_obj',variables.cacheput_obj,createTimespan(0,0,0,30),createTimespan(0,0,0,30),variables.cacheNames[1]);
        if(cacheIdExists('cacheput_obj',variables.cacheNames[1])){
            WriteDump(var={
                cacheExist = true
            },output="C:\domains\acf-lucee-shared\logs\la_code_application_onRequestStart_160122.htm",format="html");
        }
Gives me:
OK. I have found out what was happening. When I used EHCache, I got the properties, I was expecting:
Copy code
variables.szCacheName = "CONFIGSETTINGS";
        variables.szApplicationName = "LA-EPORTFOLIO";
        variables.szPropertiesCachename = ucase(variables.szApplicationName) & "_" & ucase(variables.szCacheName);
        variables.stuCacheProps = {
            CLEARONFLUSH = true,
            DISKPERSISTENT = true,
            ETERNAL = true,
            MAXELEMENTSINMEMORY = 1000000,
            MAXELEMENTSONDISK = 0,
            OBJECTTYPE = "OBJECT",
            OVERFLOWTODISK = true,
            STATISTICS = true,
            TIMETOLIVESECONDS = 0,
            TIMETOIDLESECONDS = 0
        };

        this.cache.connections[variables.szPropertiesCachename] = {
            class: 'org.lucee.extension.cache.eh.EHCache',
            custom: variables.stuCacheProps,
            default: 'object'
        };
        this.cache.object = 'default';
Hi Zackster I have successfully set up the cache in my Application.cfc I am just wondering how long the cache exists. I mean can I do this kind of thing: Application.cfc
Copy code
this.SessionTimeout="#CreateTimeSpan( 0, 1, 0, 0 )#";
this.applicationtimeout="#CreateTimeSpan( 30, 0, 0, 0 )#";
this.clientmanagement="Yes";
this.clientstorage="cookie";
this.LoginStorage="session";

// CACHE INIT

variables.szCacheName = "CONFIGSETTINGS";
variables.szApplicationName = "LA-EPORTFOLIO";
variables.szPropertiesCachename = ucase(variables.szApplicationName) & "_" & ucase(variables.szCacheName);
variables.stuCacheProps = {
	CLEARONFLUSH = true,
	DISKPERSISTENT = true,
	ETERNAL = true,
	MAXELEMENTSINMEMORY = 1000000,
	MAXELEMENTSONDISK = 0,
	OBJECTTYPE = "OBJECT",
	OVERFLOWTODISK = true,
	STATISTICS = true,
	TIMETOLIVESECONDS = 0,
	TIMETOIDLESECONDS = 0
};

variables.cacheExists = StructKeyExists(this,"cache") AND StructKeyExists(this.cache,"connections") AND StructKeyExists(this.cache.connections,variables.szPropertiesCachename) ? true : false;

if(NOT variables.cacheExists){
	this.cache.connections[variables.szPropertiesCachename] = {
		class: 'org.lucee.extension.cache.eh.EHCache',
		custom: variables.stuCacheProps,
		default: 'object'
	};
	this.cache.object = 'default';
}
I cannot use
cacheRegionExists()
, because it requires a web admin password? I want to avoid exposing the web admin password. Does the cache last for a certain amount time and then it expires like the application scope?
z
that's all configurable
c
You mean the cache expiration date?
z
both per cache item and per cache
🙏 1
c
Are defaults set for the cache expiration date?
z
what do the function docs say, what does the admin interface say?
c
It doesn't really say anything about expiration: https://docs.lucee.org/guides/cookbooks/caches-in-application-cfc.html
z
image.png
c
What I mean is that if I just initialise like:
Copy code
this.cache.connections[variables.szPropertiesCachename] = {
   class: 'org.lucee.extension.cache.eh.EHCache',
   custom: variables.stuCacheProps,
  default: 'object'
};
this.cache.object = 'default';
Rather than:
Copy code
if(NOT variables.cacheExists){
   this.cache.connections[variables.szPropertiesCachename] = {
      class: 'org.lucee.extension.cache.eh.EHCache',
      custom: variables.stuCacheProps,
      default: 'object'
   };
   this.cache.object = 'default';
}
Will the cache be overwritten on every page request? Or will the cache structure last forever? Basically, can I get rid of this conditional:
Copy code
if(NOT variables.cacheExists){
   ...
I understand that each cache object has an expiry, but what about the cache itself? 🙂