As one of the hardening tasks defined for Tomcat, I'm supposed to change the output of $CATALINA_HOME/bin/version.sh to output bogus values.
This seemed pretty straight-forward from what I could find. All of the articles essentially pointed towards: extract ServerInfo.properties from catalina.jar, modify it, recommit it, and restart Tomcat.
In the stateless container world though, I have to extract it, modify it, recommit it, START tomcat. If I restart the container after tomcat is started, the container dies. Here are the steps I tried in my container entrypoint shell script:
jar -xf /opt/tomcat/lib/catalina.jar org/apache/catalina/util/ServerInfo.properties
sed -i 's#server.info=.*#server.info=Server#' /opt/tomcat/org/apache/catalina/util/ServerInfo.properties
sed -i 's#server.number=.*#server.info=0.0#' /opt/tomcat/org/apache/catalina/util/ServerInfo.properties
jar -uf /opt/tomcat/lib/catalina.jar org/apache/catalina/util/ServerInfo.properties
However, in 9.0.45, the recommit back to catalina.jar throws an error:
jar: Package org.apache.catalina.ssi missing from ModulePackages class file attribute
Investigating this, I found this article: jar: Package org.apache.catalina.ssi missing from ModulePackages class file attribute
...which essentially said it's a bug in newer versions of tomcat and the guy who got around it used 7zip instead of jar. So I modified my code with the following:
mkdir -p /opt/tomcat/test
pushd /opt/tomcat/test
7z x -y /opt/tomcat/lib/catalina.jar:org/apache/catalina/util/ServerInfo.properties
sed -i 's#server.info=.*#server.info=Server#' /opt/tomcat/test/ServerInfo.properties
sed -i 's#server.number=.*#server.info=0.0#' /opt/tomcat/test/ServerInfo.properties
7z u /opt/tomcat/lib/catalina.jar:org/apache/catalina/util/ServerInfo.properties /opt/tomcat/test/ServerInfo.properties
popd
...while this did work in-so-far as I can tell (the ServerInfo.properties file in the backup location (test) did successfully get modified and I received a success indicator from 7zip in the container console log output for the recommit), after tomcat starts and I run version.sh, it still reports the actual verison.
To reiterate, these changes are being applied before tomcat is ever started so even though all of the documentation says to restart tomcat after-the-change, I'm expecting that I shouldn't have to restart tomcat (again, since this operation kills the container and wipes any interactive container changes (stateless)).
EDIT 1:
In an effort to confirm, after the container is started, I've exec'd into the container to verify that the entrypoint script was successful. I manually extracted the file out of catalina.jar and verified that the operations did appear to be successful because the interactively-extracted ServerInfo.properties from catalina.jar does reflect the changes (so the process appears to have worked) but running $CATALINA_HOME/bin/version.sh still shows the actual version...
There is another option which is much easier and works just fine.
Alternatively, the version number can be changed by creating the file CATALINA_BASE/lib/org/apache/catalina/util/ServerInfo.properties with content as follows...
https://tomcat.apache.org/tomcat-9.0-doc/security-howto.html#web.xml
You don't need to replace anything in catalina.jar
Just create this extra config file as follows, that is enough.
mkdir -p "${CATALINA_HOME}/lib/org/apache/catalina/util"
echo "server.info=X" > "${CATALINA_HOME}/lib/org/apache/catalina/util/ServerInfo.properties"
## proceed with tomcat start...
Bonus
Remove server info from HTTP headers in server responses (also check this).
## turn off server info and stacktraces on error pages
file="${CATALINA_HOME}"/conf/server.xml
xmlstarlet edit -L \
--delete "//Connector[starts-with(#protocol, 'HTTP')]/#server" \
--insert "//Connector[starts-with(#protocol, 'HTTP')]" -t attr -n "server" -v "X" \
--delete "//Valve[#className='org.apache.catalina.valves.ErrorReportValve']" \
--subnode "/Server/Service[#name='Catalina']/Engine[#name='Catalina']/Host[#name='localhost']" -t elem -n "Valve" \
--insert "/Server/Service[#name='Catalina']/Engine[#name='Catalina']/Host[#name='localhost']/Valve[not(#className)]" -t attr -n "className" -v "org.apache.catalina.valves.ErrorReportValve" \
--insert "//Valve[#className='org.apache.catalina.valves.ErrorReportValve']" -t attr -n "showReport" -v "false" \
--insert "//Valve[#className='org.apache.catalina.valves.ErrorReportValve']" -t attr -n "showServerInfo" -v "false" \
${file}
Related
I am trying to edit the standalone.xml through docker and trying to add but the keycloak is taking its standalone.xml . But I am able to see the changes inside the standalone.xml file. I need to add this line in standalone.xml file
<provider>module:org.keycloak.examples.event-sysout</provider>
Also tried hot deployement but then can't fetch third party libraries code
First, it seems in a docker container by default standalone-ha.xml is used. You can find this in /opt/jboss/tools/docker-entrypoint.sh.
Second, I think after changing configuration file you'll have to restart keycloak server (container).
Not sure what do you mean by "dynamically". But it will be easier to modify the file locally and build a custom docker image. Dockerfile may look like:
FROM jboss/keycloak:6.0.1
ADD <path on your system>/standalone-ha.xml /opt/jboss/keycloak/standalone/configuration/standalone-ha.xml
You can not replace or overwrite standalone-ha.xml/standalone.xml without jboss-cli on docker image. Only need to create a sh file and put inside startup-script folder. During initializing it will start and configure your file.
keycloak-cli
embed-server --server-config=standalone-ha.xml --std-out=echo
batch
/subsystem=keycloak-server:list-add(name=providers, value=module:org.keycloak.examples.event-sysout)
run-batch
stop-embedded-server
Dockerfile
FROM jboss/keycloak:latest
COPY keycloak.cli /opt/jboss/startup-scripts/keycloak.cli
Might be a little late . but I found out you can edit on the dockerfile.
FROM quay.io/keycloak/keycloak:11.0.0
RUN sed -i -E "s/(<staticMaxAge>)2592000(<\/staticMaxAge>)/\1\-1\2/" /opt/jboss/keycloak/standalone/configuration/standalone.xml
RUN sed -i -E "s/(<cacheThemes>)true(<\/cacheThemes>)/\1false\2/" /opt/jboss/keycloak/standalone/configuration/standalone.xml
RUN sed -i -E "s/(<cacheTemplates>)true(<\/cacheTemplates>)/\1false\2/" /opt/jboss/keycloak/standalone/configuration/standalone.xml
RUN sed -i -E "s/(<staticMaxAge>)2592000(<\/staticMaxAge>)/\1\-1\2/" /opt/jboss/keycloak/standalone/configuration/standalone-ha.xml
RUN sed -i -E "s/(<cacheThemes>)true(<\/cacheThemes>)/\1false\2/" /opt/jboss/keycloak/standalone/configuration/standalone-ha.xml
RUN sed -i -E "s/(<cacheTemplates>)true(<\/cacheTemplates>)/\1false\2/" /opt/jboss/keycloak/standalone/configuration/standalone-ha.xml
ref : https://github.com/anthonny/kit-keycloak-theme/blob/master/Dockerfile
You should go to that running docker container and change in there.
The best is, use docker manager like Kitematic https://kitematic.com/
Select running keycloak container, click EXEC icon, cd keycloak/standalone/configuration, vi standalone.xml, :wq to exit, restart docker image through Kitematic, should work
I have a script called foo.sh in my home folder.
When I navigate to this folder, and enter ./foo.sh, I get
-bash: ./foo.sh: Permission denied.
When I use sudo ./foo.sh, I get
sudo: foo.sh: command not found.
Why does this happen and how I can fix it?
Permission denied
In order to run a script the file must have an executable permission bit set.
In order to fully understand Linux file permissions you can study the documentation for the chmod command. chmod, an abbreviation of change mode, is the command that is used to change the permission settings of a file.
To read the chmod documentation for your local system , run man chmod or info chmod from the command line. Once read and understood you should be able to understand the output of running ...
ls -l foo.sh
... which will list the READ, WRITE and EXECUTE permissions for the file owner, the group owner and everyone else who is not the file owner or a member of the group to which the file belongs (that last permission group is sometimes referred to as "world" or "other")
Here's a summary of how to troubleshoot the Permission Denied error in your case.
$ ls -l foo.sh # Check file permissions of foo
-rw-r--r-- 1 rkielty users 0 2012-10-21 14:47 foo.sh
^^^
^^^ | ^^^ ^^^^^^^ ^^^^^
| | | | |
Owner| World | |
| | Name of
Group | Group
Name of
Owner
Owner has read and write access rw but the - indicates that the executable permission is missing
The chmod command fixes that. (Group and other only have read permission set on the file, they cannot write to it or execute it)
$ chmod +x foo.sh # The owner can set the executable permission on foo.sh
$ ls -l foo.sh # Now we see an x after the rw
-rwxr-xr-x 1 rkielty users 0 2012-10-21 14:47 foo.sh
^ ^ ^
foo.sh is now executable as far as Linux is concerned.
Using sudo results in Command not found
When you run a command using sudo you are effectively running it as the superuser or root.
The reason that the root user is not finding your command is likely that the PATH environment variable for root does not include the directory where foo.sh is located. Hence the command is not found.
The PATH environment variable contains a list of directories which are searched for commands. Each user sets their own PATH variable according to their needs.
To see what it is set to run
env | grep ^PATH
Here's some sample output of running the above env command first as an ordinary user and then as the root user using sudo
rkielty#rkielty-laptop:~$ env | grep ^PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
rkielty#rkielty-laptop:~$ sudo env | grep ^PATH
[sudo] password for rkielty:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin
Note that, although similar, in this case the directories contained in the PATH the non-privileged user (rkielty) and the super user are not the same.
The directory where foo.sh resides is not present in the PATH variable of the root user, hence the command not found error.
The other solutions I've seen here so far are based on some system definitions, but it's in fact possible to have sudo use the current PATH (with the env command) and/or the rest of the environment (with the -E option) just by invoking it right:
sudo -E env "PATH=$PATH" <command> [arguments]
In fact, one can make an alias out of it:
alias mysudo='sudo -E env "PATH=$PATH"'
(It's also possible to name the alias itself sudo, replacing the original sudo.)
Check for secure_path on sudo
[root#host ~]# sudo -V | grep 'Value to override'
Value to override user's $PATH with: /sbin:/bin:/usr/sbin:/usr/bin
If $PATH is being overridden use visudo and edit /etc/sudoers
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
Check that you have execute permission on the script. i.e. chmod +x foo.sh
Check that the first line of that script is #!/bin/sh or some such.
For sudo you are in the wrong directory. check with sudo pwd
You can also create a soft link to your script in one of the directories (/usr/local/bin for example) in the super user PATH. It'll then be available to the sudo.
chmod +x foo.sh
sudo ln -s path-to-foo.sh /usr/local/bin/foo
Have a look at this answer to have an idea of which directory to put soft link in.
It seems that linux will say "command not found" even if you explicitly give the path to the file.
[veeam#jsandbox ~]$ sudo /tmp/uid.sh;echo $?
sudo: /tmp/uid.sh: command not found
1
[veeam#jsandbox ~]$ chmod +x /tmp/uid.sh
[veeam#jsandbox ~]$ sudo /tmp/uid.sh;echo $?
0
It's a somewhat misleading error, however it's probably technically correct. A file is not a command until its executable, and so cannot be found.
Try chmod u+x foo.sh instead of chmod +x foo.sh if you have trouble with the guides above. This worked for me when the other solutions did not.
Regarding "command not found" when using sudo far less hackier way would be to edit secure_path.
It is perfectly described here:
https://superuser.com/questions/927512/how-to-set-path-for-sudo-commands
Ok this is my solution:
in ~/.bash_aliases just add the following:
# ADDS MY PATH WHEN SET AS ROOT
if [ $(id -u) = "0" ]; then
export PATH=$PATH:/home/your_user/bin
fi
Voila!
Now you can execute your own scripts with sudo or set as ROOT without having to do an export PATH=$PATH:/home/your_user/bin everytime.
Notice that I need to be explicit when adding my PATH since HOME for superuser is /root
If you are not so comfortable with the command line and are using Ubuntu you can solve the problem as follows:
Open the folder window where the file is located
Right click on the executable file and choose Properties
Go to the Permissions tab and highlight Allow executing file as program
With this solution you allow the user to execute the file as a program and you don't need sudo (or change the PATH environment variable for root).
It seems sudo command not found
to check whether the sudo package is installed on your system, type sudo , and press Enter . If you have sudo installed the system will display a short help message, otherwise you will see something like sudo: command not found
To install sudo, run one of the following commands using root account:
apt-get install sudo # If your system based on apt package manager
yum install sudo # If your system based on yum package manager
I am attempting to start a jar from a systemd service, in linux. The jar that I am executing assumes that within the current directory, there is an xml file. I am passing the name of that file, with the -config argument. The sample service I have created is below:
[Unit]
Description=my service
After=network.target
[Service]
Type=simple
Environment="xml_file_name=sample.xml"
ExecStart=/usr/bin/java -jar /path/to/jar/myapp.jar -config ${xml_file_name}
The service file above is placed in the /usr/lib/systemd/system directory, and is called myservice.service. I am doing the following commands to start it:
systemctl daemon-reload
systemctl stop myservice.service
systemctl start myservice.service
systemctl status myservice.service
The systemctl status myservice.service command shows that the jar file ran, but my application says that it cannot find ${xml_file_name}.
In addition, my jar states that it was executed from the / directory. I believe that this is part of the problem, because the ${xml_file_name} is only applicable in the /path/to/jar/ directory.
Things tried:
-Xbootclasspath/p:"/path/to/jar/": prepend the path of the jars
location, so that maybe the ${xml_file_name} can be seen.
changed the /path/to/jar/ to make sure it has all possible permissions enabled
I tried to add User=root under the [Service] section of my systemd service, but it made no change. Either way, only root user is on the machine, and the permissions all seem to check out.
What makes this even more strange is that if I cd to / , and then manually execute:
/usr/bin/java -jar /path/to/jar/myapp.jar -config sample.xml
everything words just fine.
Is there something evident that I am missing here? Is it possible to tell systemd service, execute this java jar, but make sure that the working path is /path/to/jar/ as opposed to / ?
To solve this, I ended up using the following attribute under the [Service] section:
[Service]
...
WorkingDirectory=/path/to/jar
ExecStart=/usr/bin/java -jar my.jar -config sample.xml
Solved the problem!
Try following:
cd /path/to/jar && /usr/bin/java -jar /path/to/jar/myapp.jar -config sample.xml
If you use && in Linux like systems, it combines the two commands in the way the second will be executed only after the first will be executed successfully. So basically it would first change the working directory and then run the java jar command from the changed directory, which could have solved the problem.
I’m trying to install JDK on Centos, but I’m getting an error:
[root#www opt]# rpm -ivh /opt/jdk-7u51-linux-x64.rpm
Preparing... ########################################### [100%]
1:jdk ########################################### [100%]
error: unpacking of archive failed on file /usr/java/jdk1.7.0_51/db/lib/derbyLocale_zh_CN.jar;533ab42a: cpio: read
Where can be problem?
Thanks
Can you please check the md5sum of the downloaded file against these values here: http://www.oracle.com/technetwork/java/javase/downloads/java-se-binaries-checksum-1956892.html ?
If the md5sum does not check, it must be a broken download.
A short answer: try downloading and installing again.
A longer answer:
Even though you are getting this, the jdk is getting installed. Sort of. This seems to be an error in the packaging but it is not fatal. Here is the output from my machine. In the example I cat'd the release file so you can see what CentOS I'm using and did an md5sum on the rpm I'm using. You'll notice that it doesn't match the md5sum from the Oracle site link (provided above by Kristof).
Next, I did an ls on the target directory for the jdk /usr/java/ so you can see that it is empty. Then ran the rpm install and did another ls to show that some files are there.
Of course, this defeats the purpose of using rpm, because the install information is not going to go into the rpm database. If I query the database it doesn't come up and it's missing the links that usually get installed pointing to 'latest' and 'default'
So I took a guess that maybe there is a mirror that might have a bad rpm and went to the Oracle site and downloaded the file again. I gave it a different name so that I can compare the two files. This time it was successful.
In the screen shot below you can see the two files. The newest download being the one I called jdk-7u51-linux-x86_64.rpm. You can see the md5sum shows the files are different, but on the new file, the md5 matches the Oracle site. I removed the directory that was created by the failed install and then ran the rpm -ivh command and it completed successfully. The ls on the /usr/java directory shows all the correct stuff and querying the rpm database shows it was installed. Hope this helps!
You can do it with simple script which you can find here
It's for Centos rpm, but you can edit script and change rpm to tar.gz for example
Also you can change version or env in variables bellow
BASE_URL="technetwork/java/javase/downloads"
BASE_URL_OUTPUT="$(curl -s -L0 http://www.oracle.com/${BASE_URL}/)"
JAVA_ENVIRONMENT="JDK"
JAVA_BASE_VERSION=8
DOWNLOAD_SITE="$(echo $BASE_URL_OUTPUT | grep -m 1 -io "${JAVA_ENVIRONMENT}${JAVA_BASE_VERSION}-downloads-[0-9]*.html" -- | tail -1)"
echo "DOWNLOAD_SITE="$DOWNLOAD_SITE
DOWNLOAD_LINK_OUTPUT="$(curl -s -L -j -H "Cookie: oraclelicense=accept-securebackup-cookie" http://www.oracle.com/${BASE_URL}/${DOWNLOAD_SITE} | grep -io "filepath.*${JAVA_ENVIRONMENT}-[${JAVA_BASE_VERSION}].*linux[-_]x64[._].*\(rpm\)" -- | cut -d '"' -f 3 | tail -1)"
echo "DOWNLOAD_LINK_OUTPUT="$DOWNLOAD_LINK_OUTPUT
curl -L -o java_rpm_packet.rpm -b "oraclelicense=a" $DOWNLOAD_LINK_OUTPUT
and install with
yum localinstall -y java_rpm_packet.rpm
I am using the Jetty/Solr build that comes with Solr and would like to run it in the background instead of in the terminal.
Right now I start it by java -jar start.jar but I would like it to log to a file and run in the background on the server so that I can close the terminal window.
I'm sure there is some java config that I can't find.
I have tried java -jar start.jar > log.txt & but no luck still outputs to the terminal window.
Thanks.
Try something like:
nohup yourcommand > output.log 2>&1 &
nohup will prevent yourcommand from being terminated in the event you log out.
& will run it in the background.
> output.log will send stdout to output.log
2>&1 will redirect stderr to stdout
nohup is used to execute commands that runs after logout from a shell. What you need here is '2>&1'. This redirects standart error to the standart output. So everything will be logged to log.txt.
Try this
java -jar start.jar > log.txt 2>&1
Also you can add an '&' start it as a background process.
You can run it with screen if you are on unix.
You can properly install it as a linux service too.
cd to your jetty folder, for example mine is:
cd /home/spydon/jetty/
They have actually made most of the work with the jetty.sh file, so copy that one to /etc/init.d/
sudo cp ./bin/jetty.sh /etc/init.d/jetty
Then open the file with your favorite text editor, like vim or nano
sudo vim /etc/init.d/jetty
In the beginning simply uncomment (remove the hash(#)) three lines that says something like:
#chkconfig: 3 99 99
#description: Jetty 9 webserver
#processname: jetty
Meanwhile you have the text editor open, also add the jetty home directory to the beginning of the file, mine now looks like this:
#!/usr/bin/env bash
#
# Startup script for jetty under *nix systems (it works under NT/cygwin too).
JETTY_HOME=/home/spydon/jetty
# To get the service to restart correctly on reboot, uncomment below (3 lines):
# ========================
chkconfig: 3 99 99
description: Jetty 9 webserver
processname: jetty
# ========================
Now you should be able to start it with
sudo /etc/init.d/jetty start
And if you want it to run every time you reboot, simply add
sudo ln -s /etc/init.d/jetty /etc/rc1.d/K99jetty
sudo ln -s /etc/init.d/jetty /etc/rc2.d/S99jetty
This should work for most modern distros, but I've only tried it on debian based ones.
You could also consider doing a symlink to the jetty.sh so it will be easier to upgrade.
You may want to try nohup, as explained in this previous answer.