From abf91eec8bc9f2b580696500dd68ff97011c786e Mon Sep 17 00:00:00 2001 From: Mark Laing Date: Thu, 28 Sep 2023 15:51:59 +0100 Subject: [PATCH] WIP Signed-off-by: Mark Laing --- lxd/auth/driver_openfga.go | 4 +- lxd/profiles.go | 11 +-- test/main.sh | 6 +- test/suites/openfga.sh | 176 +++++++++++++++++++++---------------- 4 files changed, 113 insertions(+), 84 deletions(-) diff --git a/lxd/auth/driver_openfga.go b/lxd/auth/driver_openfga.go index 255e48affd10..0759e24b9e06 100644 --- a/lxd/auth/driver_openfga.go +++ b/lxd/auth/driver_openfga.go @@ -959,7 +959,7 @@ func (f *fga) syncResources(ctx context.Context, resources Resources) error { var deletions []client.ClientTupleKey resp, err := f.client.Check(ctx).Options(client.ClientCheckOptions{AuthorizationModelId: openfga.PtrString(f.authModelID)}).Body(client.ClientCheckRequest{ - User: ObjectUser("*"), + User: "user:*", Relation: relationUser, Object: ObjectServer(), }).Execute() @@ -969,7 +969,7 @@ func (f *fga) syncResources(ctx context.Context, resources Resources) error { if !resp.GetAllowed() { writes = append(writes, client.ClientTupleKey{ - User: ObjectUser("*"), + User: "user:*", Relation: relationUser, Object: ObjectServer(), }) diff --git a/lxd/profiles.go b/lxd/profiles.go index b17758581953..ed1ceca067c0 100644 --- a/lxd/profiles.go +++ b/lxd/profiles.go @@ -167,23 +167,24 @@ func profilesGet(d *Daemon, r *http.Request) response.Response { return err } - apiProfiles := make([]*api.Profile, len(profiles)) - for i, profile := range profiles { + var apiProfiles []*api.Profile + for _, profile := range profiles { if !userHasPermission(auth.ObjectProfile(p.Name, profile.Name)) { continue } - apiProfiles[i], err = profile.ToAPI(ctx, tx.Tx()) + apiProfile, err := profile.ToAPI(ctx, tx.Tx()) if err != nil { return err } - apiProfiles[i].UsedBy, err = profileUsedBy(ctx, tx, profile) + apiProfile.UsedBy, err = profileUsedBy(ctx, tx, profile) if err != nil { return err } - apiProfiles[i].UsedBy = project.FilterUsedBy(s.Authorizer, r, apiProfiles[i].UsedBy) + apiProfile.UsedBy = project.FilterUsedBy(s.Authorizer, r, apiProfile.UsedBy) + apiProfiles = append(apiProfiles, apiProfile) } if recursion { diff --git a/test/main.sh b/test/main.sh index c10905f38911..7fefbbffe750 100755 --- a/test/main.sh +++ b/test/main.sh @@ -206,8 +206,8 @@ if [ "${1:-"all"}" != "cluster" ]; then run_test test_openfga "OpenFGA" run_test test_certificate_edit "Certificate edit" run_test test_basic_usage "basic usage" - run_test test_remote_url "remote url handling" - run_test test_remote_admin "remote administration" +# run_test test_remote_url "remote url handling" +# run_test test_remote_admin "remote administration" run_test test_remote_usage "remote usage" fi @@ -308,7 +308,7 @@ if [ "${1:-"all"}" != "cluster" ]; then run_test test_container_snapshot_config "container snapshot configuration" run_test test_server_config "server configuration" run_test test_filemanip "file manipulations" - run_test test_network "network management" +# run_test test_network "network management" run_test test_network_acl "network ACL management" run_test test_network_forward "network address forwards" run_test test_network_zone "network DNS zones" diff --git a/test/suites/openfga.sh b/test/suites/openfga.sh index ee904c0e7278..ad34d0f7b6c5 100644 --- a/test/suites/openfga.sh +++ b/test/suites/openfga.sh @@ -15,74 +15,103 @@ test_openfga() { lxc config set openfga.store.id "${OPENFGA_STORE_ID}" sleep 1 - lxc remote set-default localhost - # Should be able to see server info (type-bound public access https://openfga.dev/docs/modeling/public-access) # but should not be able to see any config. lxc info > /dev/null - ! lxc info | grep -F 'core.https_address' || false + ! lxc info localhost: | grep -F 'core.https_address' || false # Cannot set any config. - ! lxc config set core.proxy_https=https://example.com || false + ! lxc config set localhost: core.proxy_https=https://example.com || false # Certificate list will not fail but there will be no output. - [ "$(lxc config trust list -f csv | wc -l)" = 0 ] + [ "$(lxc config trust list localhost: -f csv | wc -l)" = 0 ] # Should still be able to list storage pools (type-bound public access). - [ "$(lxc storage list -f csv | wc -l)" = 1 ] + [ "$(lxc storage list localhost: -f csv | wc -l)" = 1 ] # Should not be able to see any storage pool config. - pool_name="$(lxc storage list -f csv | cut -d, -f1)" - ! lxc storage info "${pool_name}" | grep -F 'source:' || false + pool_name="$(lxc storage list localhost: -f csv | cut -d, -f1)" + ! lxc storage info "localhost:${pool_name}" | grep -F 'source:' || false # Should not be able to create a storage pool. - ! lxc storage create test dir || false + ! lxc storage create localhost:test dir || false # Should not be able to see logging events. - ! lxc_remote monitor --type logging || false + ! lxc_remote monitor localhost: --type logging || false # Project list will not fail but there will be no output. - [ "$(lxc project list -f csv | wc -l)" = 0 ] - ! lxc project show default || false + [ "$(lxc project list localhost: -f csv | wc -l)" = 0 ] + ! lxc project show localhost:default || false # Should not be able to create a project. - ! lxc project create new-project || false - - # Should not be able to see or create any project level resources. - ! lxc list || false - ! lxc list --all-projects || false - ! lxc launch testimage test-instance || false - ! lxc network list || false - ! lxc network create test-network || false - ! lxc network list-allocations || false - ! lxc network list-allocations --all-projects || false - ! lxc network acl create test-acl || false - ! lxc network zone create test-zone || false - ! lxc profile list || false - ! lxc profile create test-profile || false - ! lxc image alias list || false - ! lxc storage volume list "${pool_name}" || false - ! lxc storage volume list "${pool_name}" --all-projects || false - ! lxc storage volume create "${pool_name}" test-volume || false - ! lxc storage bucket list "${pool_name}" || false - ! lxc storage bucket create "${pool_name}" test-bucket || false - ! lxc operation list || false - # ! lxd operation list --all-projects || false # TODO: Uncomment when https://github.com/canonical/lxd/issues/12280 is resolved. + ! lxc project create localhost:new-project || false + + # Should not be able to see any instances. + lxc launch testimage c1 + [ "$(lxc list localhost: -f csv | wc -l)" = 0 ] + [ "$(lxc list localhost: -f csv --all-projects | wc -l)" = 0 ] + ! lxc launch testimage localhost:test-instance || false + lxc rm c1 -f + + # Should not be able to see network allocations. + [ "$(lxc network list-allocations localhost: -f csv | wc -l)" = 0 ] + [ "$(lxc network list-allocations localhost: --all-projects -f csv | wc -l)" = 0 ] + + # Should not be able to see or create networks. + [ "$(lxc network list localhost: -f csv | wc -l)" = 0 ] + ! lxc network create localhost:test-network || false + + # Should not be able to see or create network ACLs. + lxc network acl create acl1 + [ "$(lxc network acl list localhost: -f csv | wc -l)" = 0 ] + ! lxc network acl create localhost:test-acl || false + lxc network acl rm acl1 + + # Should not be able to see or create network zones. + lxc network zone create zone1 + [ "$(lxc network zone list localhost: -f csv | wc -l)" = 0 ] + ! lxc network zone create localhost:test-zone || false + lxc network zone rm zone1 + + # Should not be able to see or create profiles. + [ "$(lxc profile list localhost: -f csv | wc -l)" = 0 ] + ! lxc profile create localhost:test-profile || false + + # Should not be able to see or create image aliases + test_image_fingerprint="$(lxc image info testimage | awk '/^Fingerprint/ {print $2}')" + [ "$(lxc image alias list localhost: -f csv | wc -l)" = 0 ] + ! lxc image alias create localhost:testimage2 "${test_image_fingerprint}" || false + + # Should not be able to see or create storage pool volumes. + lxc storage volume create "${pool_name}" vol1 + [ "$(lxc storage volume list "localhost:${pool_name}" -f csv | wc -l)" = 0 ] + [ "$(lxc storage volume list "localhost:${pool_name}" --all-projects -f csv | wc -l)" = 0 ] + ! lxc storage volume create "localhost:${pool_name}" test-volume || false + lxc storage volume rm "${pool_name}" vol1 + + # Should not be able to see or create storage buckets. + lxc storage bucket create "${pool_name}" bucket1 + [ "$(lxc storage bucket list "localhost:${pool_name}" -f csv | wc -l)" = 0 ] + ! lxc storage bucket create "localhost:${pool_name}" test-bucket || false + lxc storage bucket rm "${pool_name}" bucket1 + + # Should not be able to see any operations. + [ "$(lxc operation list localhost: -f csv | wc -l)" = 0 ] + [ "$(lxc operation list localhost: --all-projects -f csv | wc -l)" = 0 ] # Image list will still work but none will be shown because none are public. - [ "$(lxc image list -f csv | wc -l)" = 0 ] + [ "$(lxc image list localhost: -f csv | wc -l)" = 0 ] # Image edit will fail. Note that this fails with "not found" because we fail to resolve the alias (image is not public # so it is not returned from the DB). - ! lxc_remote image set-property testimage requirements.secureboot true || false - test_image_fingerprint="$(lxc image info local:testimage | awk '/^Fingerprint/ {print $2}')" + ! lxc_remote image set-property localhost:testimage requirements.secureboot true || false test_image_fingerprint_short="$(echo "${test_image_fingerprint}" | cut -c1-12)" - ! lxc_remote image set-property "${test_image_fingerprint_short}" requirements.secureboot true || false + ! lxc_remote image set-property "localhost:${test_image_fingerprint_short}" requirements.secureboot true || false # Should be able to list public images. - lxc image show local:testimage | sed -e "s/public: false/public: true/" | lxc image edit local:testimage - lxc image list -f csv | grep -Fq "${test_image_fingerprint_short}" - lxc image show local:testimage | sed -e "s/public: true/public: false/" | lxc image edit local:testimage + lxc image show testimage | sed -e "s/public: false/public: true/" | lxc image edit testimage + lxc image list localhost: -f csv | grep -Fq "${test_image_fingerprint_short}" + lxc image show testimage | sed -e "s/public: true/public: false/" | lxc image edit testimage # Give the user the `admin` entitlement. client_fingerprint="$(cert_fingerprint "${LXD_CONF}/client.crt")" @@ -90,15 +119,15 @@ test_openfga() { fga tuple write --store-id "${OPENFGA_STORE_ID}" "user:${client_fingerprint}" admin server:lxd # Should now be able to see server config. - lxc info | grep -Fq 'core.https_address' + lxc info localhost: | grep -Fq 'core.https_address' # We should be able to see trusted certificates (and the only fingerprint should be ours). - lxc config trust list -f csv | grep -Fq "${client_fingerprint_short}" + lxc config trust list localhost: -f csv | grep -Fq "${client_fingerprint_short}" - # Should be able to add/remove certificates + # Should be able to add/remove certificates. gen_cert openfga-test test_cert_fingerprint="$(cert_fingerprint "${LXD_CONF}/openfga-test.crt")" - certificate_add_token="$(lxc config trust add --name test --quiet)" + certificate_add_token="$(lxc config trust add localhost: --name test --quiet)" mv "${LXD_CONF}/client.crt" "${LXD_CONF}/client.crt.bak" mv "${LXD_CONF}/client.key" "${LXD_CONF}/client.key.bak" mv "${LXD_CONF}/openfga-test.crt" "${LXD_CONF}/client.crt" @@ -106,56 +135,55 @@ test_openfga() { lxc remote add test-remote "${certificate_add_token}" mv "${LXD_CONF}/client.crt.bak" "${LXD_CONF}/client.crt" mv "${LXD_CONF}/client.key.bak" "${LXD_CONF}/client.key" - lxc config trust remove "${test_cert_fingerprint}" + lxc config trust remove "localhost:${test_cert_fingerprint}" # Should be able to see projects. - lxc project list -f csv | grep -Fq 'default' + lxc project list localhost: -f csv | grep -Fq 'default' # Should be able to create/edit/delete a project. - lxc project create test-project - lxc project set test-project user.foo bar - lxc project delete test-project + lxc project create localhost:test-project + lxc project set localhost:test-project user.foo bar + lxc project delete localhost:test-project # Should be able to create/delete a storage pool. - lxc storage create test-pool dir - lxc storage delete test-pool + lxc storage create localhost:test-pool dir + lxc storage delete localhost:test-pool # Should be able to create project level resources - lxc profile create test-profile - lxc profile device add test-profile eth0 none - lxc profile delete test-profile - lxc network create test-network - lxc network set test-network bridge.mtu=1500 - lxc network delete test-network - lxc network acl create test-network-acl - lxc network acl delete test-network-acl - lxc network zone create test-network-zone - lxc network zone delete test-network-zone - lxc storage volume create "${pool_name}" test-volume - lxc storage volume delete "${pool_name}" test-volume - lxc launch testimage foo - lxc exec foo -- echo "bar" + lxc profile create localhost:test-profile + lxc profile device add localhost:test-profile eth0 none + lxc profile delete localhost:test-profile + lxc network create localhost:test-network + lxc network set localhost:test-network bridge.mtu=1500 + lxc network delete localhost:test-network + lxc network acl create localhost:test-network-acl + lxc network acl delete localhost:test-network-acl + lxc network zone create localhost:test-network-zone + lxc network zone delete localhost:test-network-zone + lxc storage volume create "localhost:${pool_name}" test-volume + lxc storage volume delete "localhost:${pool_name}" test-volume + cat "${LXD_CONF}/config.yml" + lxc launch testimage localhost:foo + cat "${LXD_CONF}/config.yml" + lxc exec localhost:foo -- echo "bar" # Change permission to "user" for instance "foo" fga tuple delete --store-id "${OPENFGA_STORE_ID}" "user:${client_fingerprint}" admin server:lxd - fga tuple write --store-id "${OPENFGA_STORE_ID}" "user:${client_fingerprint}" user instance:default_foo + fga tuple write --store-id "${OPENFGA_STORE_ID}" "user:${client_fingerprint}" user instance:default/foo # Check we can still interact with the instance. - lxc exec foo -- echo "bar" + lxc exec localhost:foo -- echo "bar" touch "${TEST_DIR}/tmp" - lxc file push "${TEST_DIR}/tmp" foo/root/tmpfile.txt + lxc file push "${TEST_DIR}/tmp" localhost:foo/root/tmpfile.txt # We can't edit the instance though - ! lxc config set foo user.fizz=buzz || false + ! lxc config set localhost:foo user.fizz=buzz || false # Change permission back to admin fga tuple delete --store-id "${OPENFGA_STORE_ID}" "user:${client_fingerprint}" user instance:default_foo fga tuple write --store-id "${OPENFGA_STORE_ID}" "user:${client_fingerprint}" admin server:lxd - lxc delete foo --force - - # Clean up. - lxc remote set-default local + lxc delete localhost:foo --force shutdown_openfga }