Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix CA generation as non-root user due to .rnd error #929

Merged
merged 1 commit into from
Mar 27, 2024

Conversation

BrooklynDewolf
Copy link
Contributor

@BrooklynDewolf BrooklynDewolf commented Mar 15, 2024

Changes introduced with this PR

  • The engine-setup was giving issues when generating the .pem files, because the directory was not changed early enough. This has been fixed

Are you the owner of the code you are sending in, or do you have permission of the owner?

Yes

Co-authored-by: Jean-Louis Dupond [email protected]
Signed-off-by: Brooklyn Dewolf [email protected]

@BrooklynDewolf BrooklynDewolf force-pushed the fix/OV-17 branch 4 times, most recently from a70829c to 99fe131 Compare March 15, 2024 15:55
@BrooklynDewolf BrooklynDewolf changed the title FIx OpenSSL problem during engine-setup Fix CA generation as non-root user due to .rnd error Mar 15, 2024
@mwperina
Copy link
Member

/ost

@didib
Copy link
Member

didib commented Mar 18, 2024

Sorry, I do not understand the problem this should fix, nor what caused it to surface suddenly. Is it a change in openssl (genpkey or req)?

In theory, moving the 'cd ' outside of the subshell starting in line 88 is significant - affects also e.g. keytool.

@didib
Copy link
Member

didib commented Mar 18, 2024

I think that developer mode did work at least at some point after this code was written (~ 11 years ago, based on the git log). I also searched and found now something I wrote many years ago and never get to actually publishing. Might be useful, so putting in a separate comment.

@didib
Copy link
Member

didib commented Mar 18, 2024

How to use ovirt-engine's CA scripts to run a separate CA

The scripts were not designed to allow this, but do not have too many hard-coded paths either. So it's not hard to make them use a different directory.

To create your own copy

MYCADIR=$HOME/testca
MYPKIDIR="${MYCADIR}/pki"
MYBINDIR="${MYCADIR}/bin"

FQDN="my-ca-common-name.example.org"
AIA="caIssuers;URI:http://${FQDN}:80/ca.crt"
CA_SUBJECT="/C=US/O=eng.lab.tlv.redhat.com/CN=${FQDN}.ca"
SUBJECT="/C=US/O=eng.lab.tlv.redhat.com/CN=${FQDN}.ca"
PKIPASS=topsecret

mkdir -p "${MYCADIR}" "${MYPKIDIR}" "${MYBINDIR}"

cp /usr/share/ovirt-engine/bin/pki-* "${MYBINDIR}"
sed -i -e "s;^PKIDIR.;PKIDIR="${MYPKIDIR}";" -e "s;^USRDIR.;USRDIR="${MYCADIR}";" "${MYBINDIR}"/pki-common.sh

cd "${MYPKIDIR}"
cp /etc/pki/ovirt-engine/{*cert.template.in,openssl.conf} .

Note that this is usually done by engine-setup, and we might do other replacements in the future. But currently AIA is enough.

for f in cert.template cacert.template; do sed "s#@aia@#${AIA}#" < "${f}.in" > "${f}"; done

mkdir certs keys private requests

To create your CA there

"${MYBINDIR}"/pki-create-ca.sh --subject="${CA_SUBJECT}" --keystore-password="${PKIPASS}"

To create local key

This creates a temp key, csr, signs it, packs into a pkcs12 archive, and removes the temp key. N is the prefix of used files, DN is the domain name for which we do this:

N=name1; DN=myname1.example.org; "${MYBINDIR}"/pki-enroll-pkcs12.sh --name="${N}" --password="${PKIPASS}" --subject="/C=US/O=eng.lab.tlv.redhat.com/CN=${DN}" --san="DNS:${DN}"

To extract the key to its own file without a password:

N=name1; "${MYBINDIR}"/pki-pkcs12-extract.sh --name="${N}" --passin="${PKIPASS}" --key="${MYPKIDIR}/keys/${N}".key.nopass

To create the key and csr outside of the CA, and sign in the CA

Somewhere:

openssl genrsa -out my-thing.key 2048

openssl req -new -out my-thing.csr -key my-thing.key

Copy the csr to the CA, e.g. if on same machine:

cp my-thing.csr "${MYPKIDIR}"/requests/name2.req

Then, to sign, on the CA machine:

N=name2; DN=myname2.example.org; "${MYBINDIR}"/pki-enroll-request.sh --name=${N} --subject="/C=US/O=myorg.redhat.com/CN=${DN}" --san="DNS:${DN}"

Your generated certs are in $MYPKIDIR/certs , in both cases.

To put everything where [1] expects them

[1] https://access.redhat.com/documentation/en-us/red_hat_virtualization/4.2/html/administration_guide/appe-red_hat_enterprise_virtualization_and_ssl#Replacing_the_Manager_CA_Certificate

cp ca.pem /tmp/3rd-party-ca-cert.pem
cp keys/name1.key.nopass /tmp/apache.key
cp certs/name1.cer /tmp/apache.cer

@didib
Copy link
Member

didib commented Mar 18, 2024

Considering the reference to RHV 4.2 docs, I suppose I tested it at the time and it worked. No idea about later versions.

@dupondje
Copy link
Member

Thanks for the review @didib

The issue only occurs when you run engine-setup as a non-root user.

The openssl req command fails:

28467 execve("/usr/bin/openssl", ["openssl", "req", "-batch", "-config", "/home/build/ovirt//etc/pki/ovirt-engine/cacert.conf", "-new", "-key", "/home/build/ovirt//etc/pki/ovirt-engine/private/ca.pem", "-out", "/home/build/ovirt//etc/pki/ovirt-engine/requests/ca.csr", "-subj", "/"], 0x5a7ca1ba52e0 /* 60 vars */) = 0

Is executed AT_FDCWD (which is not changed by the script), and in that folder openssl tries to find the .rnd file.
Which does not exist:

28467 openat(AT_FDCWD, ".rnd", O_RDONLY) = -1 ENOENT (No such file or directory)
28467 write(2, "Can't load .rnd into RNG\n", 25) = 25
28280 <... poll resumed>)               = 1 ([{fd=11, revents=POLLIN}])
28467 write(2, "806B8A4B267F0000:error:12000079:random number generator:RAND_load_file:Cannot open file:crypto/rand/randfile.c:106:Filename=.rnd\n", 129) = 129
28280 read(11, "Can't load .rnd into RNG\n806B8A4B267F0000:error:12000079:random number generator:RAND_load_file:Cannot open file:crypto/rand/randfile.c:106:Filename=.rnd\n", 32768) = 154
28280 poll([{fd=9, events=POLLIN}, {fd=11, events=POLLIN}], 2, -1 <unfinished ...>
28467 brk(0x5633f89d7000)               = 0x5633f89d7000
28467 brk(0x5633f89d6000)               = 0x5633f89d6000
28467 futex(0x7f264befaf90, FUTEX_WAKE_PRIVATE, 2147483647) = 0
28467 getpid()                          = 28467
28467 brk(0x5633f89f7000)               = 0x5633f89f7000
28467 brk(0x5633f89f6000)               = 0x5633f89f6000
28467 getrandom("\xcd\x17\x75\x4b\x6c\x2e\x4c\x51\xb0\x5b\xee\xe8\x0b\x10\xf4\x9e\x9f\x84\x5d\xe5\xd5\x4e\x20\x82\xd9\xba\xff\xcd\xfd\x66\xfc\x81\x4d\x80\xfe\xbc\x9f\x55\x51\x07\x53\x34\x0e\xa8\xaa\x5b\xaa\x26", 48, 0) = 48
28467 getpid()                          = 28467
28467 getpid()                          = 28467
28467 getpid()                          = 28467
28467 getpid()                          = 28467
28467 openat(AT_FDCWD, "/home/build/ovirt//etc/pki/ovirt-engine/requests/ca.csr", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
28467 fstat(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
28467 write(3, "-----BEGIN CERTIFICATE REQUEST-----\nMIICRTCCAS0CAQAwADCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMio\nhS5Zr5brDeJry/n/aXzAydItYyI/hjs1ncpWFMh1YiEl8kyY8RKHPAJ9nqHcOasL\nm82txSf/Jp1a7kfPaL9O7RAwOK3gnKLd03yF91R8mphESfmQyoOrSyCa8U4lAsay\n1tBpxbskZw8efGm+xqReEVbfXBQJbmFe1q/PVYrZ6aJmCFU6BanC7L1rms5P8qGn\nTHXcYb0Mc7Xe60CoeZqt63ZQjT2Tq+ahJ3wz0096v/Hqn7xp1G50e8YJLpFEwa2t\nt/jzZA4mR1GUHxT/8EdAZefr\nHLHz9KgB3F84ruc+NGPOG7ksnMFkpW9EpZ5SReeAWd/VcoDIyY+OXPTjqqRYb6Mx\nYnh3ThR2BJNh8yUIpT3m1MnkxkEAX1Ovxr3V//5Dncb9e9I7/SGG+yox5Fk+Xpxu\nHIvydvjmJCr2KIZ+MLLBYWmR+HXvwt1fJla8auchk4PjJ/2sZ8l8f3vUA10clAY6\nHnbtDV/2SDZDBCVPFz/2FkCgsMF0Ct09C+MA0owuFoBprbAZaq6IWG1Y1Ao6m6WP\nZ0QHf3x8abybF47R6T+mYrjbtd7c+p6/AOFOAOq4NyrFqwzdWTReKogsdD1+bFI8\nbXlI7tC4i/fH\n-----END CERTIFICATE REQUEST-----\n", 863) = 863
28467 close(3)  = 0

So it will try to create one, which fails, cause it does not have permissions on the current CWD:

28467 newfstatat(AT_FDCWD, ".rnd", 0x7ffd2481ab10, 0) = -1 ENOENT (No such file or directory)
28467 getpid()                          = 28467
28467 openat(AT_FDCWD, ".rnd", O_WRONLY|O_CREAT, 0600) = -1 EACCES (Permission denied)
28467 openat(AT_FDCWD, ".rnd", O_WRONLY|O_CREAT|O_TRUNC, 0666) = -1 EACCES (Permission denied)
28467 write(2, "Cannot write random bytes:\n", 27) = 27

This can be properly fixed by changing the CWD before running the openssl req command.
But it can indeed be changed inside the subshell and just move the openssl req command in the subshell.

@didib
Copy link
Member

didib commented Mar 18, 2024

I do not object to merging.

The purpose is not completely clear. I suggest to document this properly. If it makes sense to fit into the commit message, please do. If it's part of a larger project, perhaps link to a relevant document.

Generally speaking, engine-setup supports only one of:

  1. Developer mode - basically follow README.md (and the older and likely-out-of-date [1]), with the aim of running this on a developer laptop, without interfering with the OS and being able to easily clean up and start from scratch
  2. "Non-developer-mode" ("Production mode"? We do not have a term): Things are done on the live system as installed from RPMs, changing /etc etc. as needed. Undoing this can be done with engine-cleanup, but that's less robust, at least if using buggy development versions. Developers used this mode for development mainly on scratch VMs, and it was less comfortable for debugging engine Java code (for which this was done).

For engine-setup, the condition for deciding what mode you are in is simply based on the UID. If it's root, no question. Otherwise, we ask, and abort if user does not ack. packaging/setup/plugins/ovirt-engine-common/base/core/misc.py .

It seems like you are trying to do something in between. Right? I suspect it will require some more work.

In principle, developer-mode can work also on non-RPM systems - I know of someone in the distant past using it on gentoo.

[1] https://www.ovirt.org/develop/developer-guide/engine/engine-development-environment.html

@dupondje
Copy link
Member

@didib : We are creating a docker development container to be able to build/test oVirt on any local machine if it has docker :)
That PR will come soon. But just already sending in PR's with issues we've hit during the process.

engine-setup fails creating the CA certificate when running under non-root user with the following error:

---------

plugin.execute:923 execute-output: ('/home/build/**FILTERED**//share/**FILTERED**-engine/bin/pki-create-ca.sh', '--subject=/C=US/O=Test/CN=c0714690d92b.71630', '--keystore-password=**FILTERED**', '--ca-file=ca') stderr:
Can't load .rnd into RNG
803BCAC12B7F0000:error:12000079:random number generator:RAND_load_file:Cannot open file:crypto/rand/randfile.c:106:Filename=.rnd
Cannot write random bytes:
803BCAC12B7F0000:error:12000079:random number generator:RAND_write_file:Cannot open file:crypto/rand/randfile.c:240:Filename=.rnd
Cannot generate CA request

----------

openssl commands try to find a .rnd file in the current directly. If not found, it will be created.
But as we do not change early enough into the correct path, the .rnd file can't be created there, resulting in an error.
So we just switch move the openssl req command in the subshell in the correct PKIDIR path.

Signed-off-by: Brooklyn Dewolf <[email protected]>
Signed-off-by: Jean-Louis Dupond <[email protected]>
@dupondje
Copy link
Member

No code change, just fix Signed-off-by :)

@didib
Copy link
Member

didib commented Mar 18, 2024

/ost

@sandrobonazzola
Copy link
Member

Merging based on previous approvals

@sandrobonazzola sandrobonazzola merged commit 14bca05 into oVirt:master Mar 27, 2024
4 checks passed
@sandrobonazzola sandrobonazzola added this to the ovirt-4.5.7 milestone Oct 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants