Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Laing <[email protected]>
  • Loading branch information
markylaing committed Sep 28, 2023
1 parent 872499c commit abf91ee
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 84 deletions.
4 changes: 2 additions & 2 deletions lxd/auth/driver_openfga.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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(),
})
Expand Down
11 changes: 6 additions & 5 deletions lxd/profiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions test/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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"
Expand Down
176 changes: 102 additions & 74 deletions test/suites/openfga.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,147 +15,175 @@ 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")"
client_fingerprint_short="$(echo "${client_fingerprint}" | cut -c1-12)"
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"
mv "${LXD_CONF}/openfga-test.key" "${LXD_CONF}/client.key"
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
}

0 comments on commit abf91ee

Please sign in to comment.