Skip to content

Commit

Permalink
PKI test improvements (#14213)
Browse files Browse the repository at this point in the history
There was a test failure when I last pushed #14207
(https://github.com/canonical/lxd/actions/runs/11183415209/job/31092412149#step:12:64275)
that led to me noticing a few things we could do better in this test:
1. When asserting that a truststore entry is added, we should grep for
exactly what we expect (e.g. more than just the common name).
2. When asserting that a truststore entry has not been added, we
shouldn't grep for anything (nothing to grep for, also what if a
truststore entry is added with a name we don't expect). We should check
that the number of entries is what is expected.
3. When in the subshell, we always should be talking to the LXD running
in `LXD5_DIR`. The setting of `LXD_DIR="${LXD5_DIR}"` preceding a
command was missed in some cases, meaning that we were checking the
output of the wrong LXD. To fix these, `LXD5_DIR` is exported as
`LXD_DIR` in the subshell.
  • Loading branch information
tomponline authored Oct 7, 2024
2 parents a8ff668 + e44fc86 commit 6d24ac3
Showing 1 changed file with 33 additions and 21 deletions.
54 changes: 33 additions & 21 deletions test/suites/pki.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ test_pki() {
token="$(LXD_DIR=${LXD5_DIR} lxc config trust add --name foo --quiet --project default)"
lxc_remote remote add pki-lxd "${LXD5_ADDR}" --accept-certificate --token "${token}"

cert_common_name="$(openssl x509 -noout -subject -in "${LXD_CONF}/client.crt" -nameopt multiline | awk -F' = ' '/commonName/ {print $2}')"
LXD_DIR="${LXD5_DIR}" lxc config trust list --format csv | grep -F "client,foo,${cert_common_name},$(cert_fingerprint "${LXD_CONF}/client.crt" | cut -c1-12)"

# Shutdown LXD. The CA certificate and revokation list must be present at start up to enable PKI.
shutdown_lxd "${LXD5_DIR}"
cp "${TEST_DIR}/pki/keys/ca.crt" "${LXD5_DIR}/server.ca"
Expand All @@ -63,6 +66,7 @@ test_pki() {
set -e
# shellcheck disable=2030
export LXD_CONF="${LXC5_DIR}"
export LXD_DIR="${LXD5_DIR}"

### Unrestricted CA signed client certificate with `core.trust_ca_certificates` disabled.

Expand All @@ -71,18 +75,20 @@ test_pki() {
cp "${TEST_DIR}/pki/keys/unrestricted.key" "${LXD_CONF}/client.key"
cp "${TEST_DIR}/pki/keys/ca.crt" "${LXD_CONF}/client.ca"
cat "${LXD_CONF}/client.crt" "${LXD_CONF}/client.key" > "${LXD_CONF}/client.pem"
fingerprint="$(cert_fingerprint "${LXD_CONF}/client.crt")"

# Try adding remote using an incorrect token. This should fail even though the client certificate
# has been signed by the CA because `core.trust_ca_certificates` is not enabled.
! lxc_remote remote add pki-lxd "${LXD5_ADDR}" --accept-certificate --token=bar || false

# Add remote using the correct token.
# This should work because the client certificate is signed by the CA.
token="$(LXD_DIR=${LXD5_DIR} lxc config trust add --name foo -q)"
token="$(lxc config trust add --name foo -q)"
lxc_remote remote add pki-lxd "${LXD5_ADDR}" --accept-certificate --token "${token}"

# Should have trust store entry because `core.trust_ca_certificates` is disabled.
lxc_remote config trust ls pki-lxd: | grep -wF unrestricted
lxc_remote config trust list pki-lxd: --format csv | grep -F "client,foo,unrestricted,$(printf '%.12s' "${fingerprint}")"
[ "$(lxc config trust list --format csv | wc -l)" = 2 ]

# The certificate was not restricted, so should be able to view server config
lxc_remote info pki-lxd: | grep -F 'core.https_address'
Expand All @@ -103,39 +109,42 @@ test_pki() {

# Remove cert from truststore.
fingerprint="$(cert_fingerprint "${LXD_CONF}/client.crt")"
LXD_DIR="${LXD5_DIR}" lxc config trust remove "${fingerprint}"
lxc config trust remove "${fingerprint}"
lxc_remote remote remove pki-lxd
[ "$(lxc config trust list --format csv | wc -l)" = 1 ]

# The certificate is now revoked, we shouldn't be able to re-add it.
token="$(LXD_DIR=${LXD5_DIR} lxc config trust add --name foo -q)"
token="$(lxc config trust add --name foo -q)"
! lxc_remote remote add pki-lxd "${LXD5_ADDR}" --accept-certificate --token "${token}" || false
! lxc config trust ls | grep -wF unrestricted || false
[ "$(lxc config trust list --format csv | wc -l)" = 1 ]

### Restricted CA signed client certificate with `core.trust_ca_certificates` disabled.

# Set up the client config
cp "${TEST_DIR}/pki/keys/restricted.crt" "${LXD_CONF}/client.crt"
cp "${TEST_DIR}/pki/keys/restricted.key" "${LXD_CONF}/client.key"
cat "${LXD_CONF}/client.crt" "${LXD_CONF}/client.key" > "${LXD_CONF}/client.pem"
fingerprint="$(cert_fingerprint "${LXD_CONF}/client.crt")"

# Try adding remote using an incorrect token. This should fail even though the client certificate
# has been signed by the CA because `core.trust_ca_certificates` is not enabled.
! lxc_remote remote add pki-lxd "${LXD5_ADDR}" --accept-certificate --token=bar || false

# Add remote using the correct token (restricted).
# This should work because the client certificate is signed by the CA.
token="$(LXD_DIR=${LXD5_DIR} lxc config trust add --name foo --quiet --restricted)"
token="$(lxc config trust add --name foo --quiet --restricted)"
lxc_remote remote add pki-lxd "${LXD5_ADDR}" --accept-certificate --token "${token}"

# Should have a trust store entry because `core.trust_ca_certificates` is disabled.
lxc_remote config trust ls pki-lxd: | grep -wF restricted
lxc_remote config trust list pki-lxd: --format csv | grep -F "client,foo,restricted,$(printf '%.12s' "${fingerprint}")"
[ "$(lxc config trust list --format csv | wc -l)" = 2 ]

# The certificate was restricted, so should not be able to view server config
! lxc_remote info pki-lxd: | grep -F 'core.https_address' || false
! curl -s --cert "${LXD_CONF}/client.pem" --cacert "${LXD5_DIR}/server.crt" "https://${LXD5_ADDR}/1.0" | jq -e '.metadata.config."core.https_address"' || false

# Enable `core.trust_ca_certificates`.
LXD_DIR=${LXD5_DIR} lxc config set core.trust_ca_certificates true
lxc config set core.trust_ca_certificates true

# The certificate was restricted, so should not be able to view server config even though `core.trust_ca_certificates` is now enabled.
! lxc_remote info pki-lxd: | grep -F 'core.https_address' || false
Expand All @@ -156,16 +165,17 @@ test_pki() {

# Remove cert from truststore.
fingerprint="$(cert_fingerprint "${LXD_CONF}/client.crt")"
LXD_DIR="${LXD5_DIR}" lxc config trust remove "${fingerprint}"
lxc config trust remove "${fingerprint}"
[ "$(lxc config trust list --format csv | wc -l)" = 1 ]
lxc_remote remote remove pki-lxd

# Unset `core.trust_ca_certificates`.
LXD_DIR=${LXD5_DIR} lxc config unset core.trust_ca_certificates
lxc config unset core.trust_ca_certificates

# The certificate is now revoked, we shouldn't be able to re-add it.
token="$(LXD_DIR=${LXD5_DIR} lxc config trust add --name foo -q)"
token="$(lxc config trust add --name foo -q)"
! lxc_remote remote add pki-lxd "${LXD5_ADDR}" --accept-certificate --token "${token}" || false
! lxc config trust ls | grep -wF restricted || false
[ "$(lxc config trust list --format csv | wc -l)" = 1 ]

### CA signed certificate with `core.trust_ca_certificates` enabled.

Expand All @@ -175,16 +185,17 @@ test_pki() {
cp "${TEST_DIR}/pki/keys/ca-trusted.crt" "${LXD_CONF}/client.crt"
cp "${TEST_DIR}/pki/keys/ca-trusted.key" "${LXD_CONF}/client.key"
cat "${LXD_CONF}/client.crt" "${LXD_CONF}/client.key" > "${LXD_CONF}/client.pem"
fingerprint="$(cert_fingerprint "${LXD_CONF}/client.crt")"

# Enable `core.trust_ca_certificates`.
LXD_DIR=${LXD5_DIR} lxc config set core.trust_ca_certificates true
lxc config set core.trust_ca_certificates true

# Add remote using a CA-signed client certificate, and not providing a token.
# This should succeed because `core.trust_ca_certificates` is enabled.
lxc_remote remote add pki-lxd "${LXD5_ADDR}" --accept-certificate

# Client cert should not be present in trust store.
! lxc_remote config trust ls pki-lxd: | grep -wF ca-trusted || false
[ "$(lxc config trust list --format csv | wc -l)" = 1 ]

# Remove remote
lxc_remote remote remove pki-lxd
Expand All @@ -194,7 +205,7 @@ test_pki() {
lxc_remote remote add pki-lxd "${LXD5_ADDR}" --accept-certificate --token=bar

# Client cert should not be present in trust store.
! lxc_remote config trust ls pki-lxd: | grep -wF ca-trusted || false
[ "$(lxc config trust list --format csv | wc -l)" = 1 ]

# The certificate is trusted as root because `core.trust_ca_certificates` is enabled.
lxc_remote info pki-lxd: | grep -F 'core.https_address'
Expand All @@ -209,7 +220,7 @@ test_pki() {
[ "$(curl -s --cert "${LXD_CONF}/client.pem" --cacert "${LXD5_DIR}/server.crt" "https://${LXD5_ADDR}/1.0/instances" | jq -e -r '.error')" = "not authorized" ]

# Re-enable `core.trust_ca_certificates`.
LXD_DIR=${LXD5_DIR} lxc config set core.trust_ca_certificates true
lxc config set core.trust_ca_certificates true

# Revoke the client certificate
cd "${TEST_DIR}/pki" && "${TEST_DIR}/pki/easyrsa" --batch revoke ca-trusted keyCompromise && "${TEST_DIR}/pki/easyrsa" gen-crl && cd -
Expand All @@ -236,22 +247,22 @@ test_pki() {

# Try adding a remote using a revoked client certificate, and the correct token.
# This should fail, and the revoked certificate should not be added to the trust store.
token="$(LXD_DIR=${LXD5_DIR} lxc config trust add --name foo -q)"
token="$(lxc config trust add --name foo -q)"
! lxc_remote remote add pki-lxd "${LXD5_ADDR}" --accept-certificate --token "${token}" || false
! lxc config trust ls | grep -wF prior-revoked || false
[ "$(lxc config trust list --format csv | wc -l)" = 1 ]

# Try adding a remote using a revoked client certificate, and an incorrect token.
# This should fail, as if the certificate is revoked and token is wrong then no access should be allowed.
! lxc_remote remote add pki-lxd "${LXD5_ADDR}" --accept-certificate --token=incorrect || false

# Unset `core.trust_ca_certificates` and re-test, there should be no change in behaviour as the certificate is revoked.
LXD_DIR=${LXD5_DIR} lxc config unset core.trust_ca_certificates
lxc config unset core.trust_ca_certificates

# Try adding a remote using a revoked client certificate, and the correct token.
# This should fail, and the revoked certificate should not be added to the trust store.
token="$(LXD_DIR=${LXD5_DIR} lxc config trust add --name foo -q)"
token="$(lxc config trust add --name foo -q)"
! lxc_remote remote add pki-lxd "${LXD5_ADDR}" --accept-certificate --token "${token}" || false
! lxc config trust ls | grep -wF prior-revoked || false
[ "$(lxc config trust list --format csv | wc -l)" = 1 ]

# Try adding a remote using a revoked client certificate, and an incorrect token.
# This should fail, as if the certificate is revoked and token is wrong then no access should be allowed.
Expand All @@ -268,6 +279,7 @@ test_pki() {
# mode is enabled.
token="$(LXD_DIR=${LXD5_DIR} lxc config trust add --name foo -q)"
! lxc_remote remote add pki-lxd2 "${LXD5_ADDR}" --accept-certificate --token "${token}" || false
[ "$(LXD_DIR="${LXD5_DIR}" lxc config trust list --format csv | wc -l)" = 1 ]

# Confirm that the certificate we added earlier cannot authenticate with LXD.
lxc_remote info pki-lxd: | grep -F 'auth: untrusted'
Expand Down

0 comments on commit 6d24ac3

Please sign in to comment.