The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6952

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
This is just a preview in order to get some feedback.

@stgraber essentially the approach that I'd take is that each of the ```restrict.*``` project configuration key has an impact on the allowed values of one or more instance-level config key. For example if you set ```restrict.containers.nesting```, then ```security.nesting``` can't be ```true``` in any container in the project.

I'm not totally sure if:
 
1. This approach will be fine for all other ```resctrict.*``` keys.
2. Which instance-level config keys and values will map to which ```restrict.X``` key(s)

However, assuming that 1. is ok, we can figure out 2. little by little as we go.
From 1e537fae51eaaaad60e388573a396f4b74f81fca Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanay...@canonical.com>
Date: Fri, 28 Feb 2020 09:21:11 +0000
Subject: [PATCH 01/10] lxd/project: Rename limits.go to permissions.go

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 lxd/project/{limits.go => permissions.go}           | 0
 lxd/project/{limits_test.go => permissions_test.go} | 0
 2 files changed, 0 insertions(+), 0 deletions(-)
 rename lxd/project/{limits.go => permissions.go} (100%)
 rename lxd/project/{limits_test.go => permissions_test.go} (100%)

diff --git a/lxd/project/limits.go b/lxd/project/permissions.go
similarity index 100%
rename from lxd/project/limits.go
rename to lxd/project/permissions.go
diff --git a/lxd/project/limits_test.go b/lxd/project/permissions_test.go
similarity index 100%
rename from lxd/project/limits_test.go
rename to lxd/project/permissions_test.go

From 4083752241b40f864ee91ae5c12f9b66c56e1b14 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanay...@canonical.com>
Date: Fri, 28 Feb 2020 09:22:48 +0000
Subject: [PATCH 02/10] lxd/project: Rename CheckLimitsUponInstanceCreation to
 AllowInstanceCreation

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 lxd/containers_post.go          |  4 ++--
 lxd/project/permissions.go      |  6 +++---
 lxd/project/permissions_test.go | 16 ++++++++--------
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/lxd/containers_post.go b/lxd/containers_post.go
index 4836d1965a..be1ef20666 100644
--- a/lxd/containers_post.go
+++ b/lxd/containers_post.go
@@ -13,7 +13,7 @@ import (
        "os"
        "strings"
 
-       "github.com/dustinkirkland/golang-petname"
+       petname "github.com/dustinkirkland/golang-petname"
        "github.com/gorilla/websocket"
        "github.com/pkg/errors"
 
@@ -825,7 +825,7 @@ func containersPost(d *Daemon, r *http.Request) 
response.Response {
                        }
                }
 
-               err := projecthelpers.CheckLimitsUponInstanceCreation(tx, 
project, req)
+               err := projecthelpers.AllowInstanceCreation(tx, project, req)
                if err != nil {
                        return err
                }
diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index f2df2467c6..b74b918feb 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -13,9 +13,9 @@ import (
        "github.com/pkg/errors"
 )
 
-// CheckLimitsUponInstanceCreation returns an error if any project-specific
-// limit is violated when creating a new instance.
-func CheckLimitsUponInstanceCreation(tx *db.ClusterTx, projectName string, req 
api.InstancesPost) error {
+// AllowInstanceCreation returns an error if any project-specific limit or
+// restriction is violated when creating a new instance.
+func AllowInstanceCreation(tx *db.ClusterTx, projectName string, req 
api.InstancesPost) error {
        project, profiles, instances, err := fetchProject(tx, projectName, true)
        if err != nil {
                return err
diff --git a/lxd/project/permissions_test.go b/lxd/project/permissions_test.go
index 89f96f4bed..d81f4fee26 100644
--- a/lxd/project/permissions_test.go
+++ b/lxd/project/permissions_test.go
@@ -12,7 +12,7 @@ import (
 )
 
 // If there's no limit configured on the project, the check passes.
-func TestCheckLimitsUponInstanceCreation_NotConfigured(t *testing.T) {
+func TestAllowInstanceCreation_NotConfigured(t *testing.T) {
        tx, cleanup := db.NewTestClusterTx(t)
        defer cleanup()
 
@@ -20,12 +20,12 @@ func TestCheckLimitsUponInstanceCreation_NotConfigured(t 
*testing.T) {
                Name: "c1",
                Type: api.InstanceTypeContainer,
        }
-       err := project.CheckLimitsUponInstanceCreation(tx, "default", req)
+       err := project.AllowInstanceCreation(tx, "default", req)
        assert.NoError(t, err)
 }
 
 // If a limit is configured and the current number of instances is below it, 
the check passes.
-func TestCheckLimitsUponInstanceCreation_Below(t *testing.T) {
+func TestAllowInstanceCreation_Below(t *testing.T) {
        tx, cleanup := db.NewTestClusterTx(t)
        defer cleanup()
 
@@ -53,13 +53,13 @@ func TestCheckLimitsUponInstanceCreation_Below(t 
*testing.T) {
                Type: api.InstanceTypeContainer,
        }
 
-       err = project.CheckLimitsUponInstanceCreation(tx, "p1", req)
+       err = project.AllowInstanceCreation(tx, "p1", req)
        assert.NoError(t, err)
 }
 
 // If a limit is configured and it matches the current number of instances, the
 // check fails.
-func TestCheckLimitsUponInstanceCreation_Above(t *testing.T) {
+func TestAllowInstanceCreation_Above(t *testing.T) {
        tx, cleanup := db.NewTestClusterTx(t)
        defer cleanup()
 
@@ -87,13 +87,13 @@ func TestCheckLimitsUponInstanceCreation_Above(t 
*testing.T) {
                Type: api.InstanceTypeContainer,
        }
 
-       err = project.CheckLimitsUponInstanceCreation(tx, "p1", req)
+       err = project.AllowInstanceCreation(tx, "p1", req)
        assert.EqualError(t, err, "Reached maximum number of instances of type 
container in project p1")
 }
 
 // If a limit is configured, but for a different instance type, the check
 // passes.
-func TestCheckLimitsUponInstanceCreation_DifferentType(t *testing.T) {
+func TestAllowInstanceCreation_DifferentType(t *testing.T) {
        tx, cleanup := db.NewTestClusterTx(t)
        defer cleanup()
 
@@ -121,6 +121,6 @@ func TestCheckLimitsUponInstanceCreation_DifferentType(t 
*testing.T) {
                Type: api.InstanceTypeContainer,
        }
 
-       err = project.CheckLimitsUponInstanceCreation(tx, "p1", req)
+       err = project.AllowInstanceCreation(tx, "p1", req)
        assert.NoError(t, err)
 }

From 4f71e94f5873bbfd4552f82470c6743061390f0c Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanay...@canonical.com>
Date: Fri, 28 Feb 2020 09:23:45 +0000
Subject: [PATCH 03/10] lxd/project: Rename CheckLimitsUponInstanceUpdate to
 AllowInstanceUpdate

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 lxd/container_patch.go     | 2 +-
 lxd/container_put.go       | 2 +-
 lxd/project/permissions.go | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/lxd/container_patch.go b/lxd/container_patch.go
index cbc609b994..cbd36fad56 100644
--- a/lxd/container_patch.go
+++ b/lxd/container_patch.go
@@ -123,7 +123,7 @@ func containerPatch(d *Daemon, r *http.Request) 
response.Response {
 
        // Check project limits.
        err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
-               return projecthelpers.CheckLimitsUponInstanceUpdate(tx, 
project, name, req)
+               return projecthelpers.AllowInstanceUpdate(tx, project, name, 
req)
        })
        if err != nil {
                return response.SmartError(err)
diff --git a/lxd/container_put.go b/lxd/container_put.go
index 443d6ad503..8cd0130301 100644
--- a/lxd/container_put.go
+++ b/lxd/container_put.go
@@ -68,7 +68,7 @@ func containerPut(d *Daemon, r *http.Request) 
response.Response {
 
        // Check project limits.
        err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
-               return projecthelpers.CheckLimitsUponInstanceUpdate(tx, 
project, name, configRaw)
+               return projecthelpers.AllowInstanceUpdate(tx, project, name, 
configRaw)
        })
        if err != nil {
                return response.SmartError(err)
diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index b74b918feb..c1ebda6590 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -109,9 +109,9 @@ func checkAggregateInstanceLimits(tx *db.ClusterTx, project 
*api.Project, instan
        return nil
 }
 
-// CheckLimitsUponInstanceUpdate returns an error if any project-specific limit
-// is violated when updating an existing instance.
-func CheckLimitsUponInstanceUpdate(tx *db.ClusterTx, projectName, instanceName 
string, req api.InstancePut) error {
+// AllowInstanceUpdate returns an error if any project-specific limit or
+// restriction is violated when updating an existing instance.
+func AllowInstanceUpdate(tx *db.ClusterTx, projectName, instanceName string, 
req api.InstancePut) error {
        project, profiles, instances, err := fetchProject(tx, projectName, true)
        if err != nil {
                return err

From 60de388f9af6fce5764e2078dee98a189bcec927 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanay...@canonical.com>
Date: Fri, 28 Feb 2020 09:24:53 +0000
Subject: [PATCH 04/10] lxd/project: Rename CheckLimitsUponProfileUpdate to
 AllowProfileUpdate

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 lxd/profiles_utils.go      | 2 +-
 lxd/project/permissions.go | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/lxd/profiles_utils.go b/lxd/profiles_utils.go
index e506d56e64..cdbfc2d623 100644
--- a/lxd/profiles_utils.go
+++ b/lxd/profiles_utils.go
@@ -18,7 +18,7 @@ import (
 func doProfileUpdate(d *Daemon, project, name string, id int64, profile 
*api.Profile, req api.ProfilePut) error {
        // Check project limits.
        err := d.cluster.Transaction(func(tx *db.ClusterTx) error {
-               return projecthelpers.CheckLimitsUponProfileUpdate(tx, project, 
name, req)
+               return projecthelpers.AllowProfileUpdate(tx, project, name, req)
        })
        if err != nil {
                return err
diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index c1ebda6590..11845c1be2 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -137,9 +137,9 @@ func AllowInstanceUpdate(tx *db.ClusterTx, projectName, 
instanceName string, req
        return nil
 }
 
-// CheckLimitsUponProfileUpdate checks that project limits are not violated
-// when changing a profile.
-func CheckLimitsUponProfileUpdate(tx *db.ClusterTx, projectName, profileName 
string, req api.ProfilePut) error {
+// AllowProfileUpdate checks that project limits and restrictions are not
+// violated when changing a profile.
+func AllowProfileUpdate(tx *db.ClusterTx, projectName, profileName string, req 
api.ProfilePut) error {
        project, profiles, instances, err := fetchProject(tx, projectName, true)
        if err != nil {
                return err

From 029593a83abc9b1192fdffbf285a2b29a094f3df Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanay...@canonical.com>
Date: Fri, 28 Feb 2020 09:25:56 +0000
Subject: [PATCH 05/10] lxd/project: Rename ValidateLimitsUponProjectUpdate to
 AllowProjectUpdate

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 lxd/api_project.go         | 2 +-
 lxd/project/permissions.go | 5 ++---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/lxd/api_project.go b/lxd/api_project.go
index 32c0ce17b7..da215c2004 100644
--- a/lxd/api_project.go
+++ b/lxd/api_project.go
@@ -358,7 +358,7 @@ func projectChange(d *Daemon, project *api.Project, req 
api.ProjectPut) response
 
        // Update the database entry
        err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
-               err := projecthelpers.ValidateLimitsUponProjectUpdate(tx, 
project.Name, req.Config, configChanged)
+               err := projecthelpers.AllowProjectUpdate(tx, project.Name, 
req.Config, configChanged)
                if err != nil {
                        return err
                }
diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index 11845c1be2..c1a6a722fd 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -164,9 +164,8 @@ func AllowProfileUpdate(tx *db.ClusterTx, projectName, 
profileName string, req a
        return nil
 }
 
-// ValidateLimitsUponProjectUpdate checks the new limits to be set on a project
-// are valid.
-func ValidateLimitsUponProjectUpdate(tx *db.ClusterTx, projectName string, 
config map[string]string, changed []string) error {
+// AllowProjectUpdate checks the new config to be set on a project is valid.
+func AllowProjectUpdate(tx *db.ClusterTx, projectName string, config 
map[string]string, changed []string) error {
        _, profiles, instances, err := fetchProject(tx, projectName, false)
        if err != nil {
                return err

From dc6bd336f0665388cf983933cdf205a682561296 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanay...@canonical.com>
Date: Fri, 28 Feb 2020 09:28:24 +0000
Subject: [PATCH 06/10] lxd/project: Rename checkAggregateInstanceLimits to
 checkRestrictionsAndAggregateLimits

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 lxd/project/permissions.go | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index c1a6a722fd..7c9b4eded7 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -35,7 +35,7 @@ func AllowInstanceCreation(tx *db.ClusterTx, projectName 
string, req api.Instanc
                Config:   req.Config,
        })
 
-       err = checkAggregateInstanceLimits(tx, project, instances, profiles)
+       err = checkRestrictionsAndAggregateLimits(tx, project, instances, 
profiles)
        if err != nil {
                return err
        }
@@ -71,9 +71,9 @@ func checkInstanceCountLimit(project *api.Project, 
instanceCount int, instanceTy
        return nil
 }
 
-// Check that we would not violate the project limits if we were to commit the
-// given instances and profiles.
-func checkAggregateInstanceLimits(tx *db.ClusterTx, project *api.Project, 
instances []db.Instance, profiles []db.Profile) error {
+// Check that we would not violate the project limits or restrictions if we
+// were to commit the given instances and profiles.
+func checkRestrictionsAndAggregateLimits(tx *db.ClusterTx, project 
*api.Project, instances []db.Instance, profiles []db.Profile) error {
        // List of config keys for which we need to check aggregate values
        // across all project instances.
        aggregateKeys := []string{}
@@ -129,7 +129,7 @@ func AllowInstanceUpdate(tx *db.ClusterTx, projectName, 
instanceName string, req
                instances[i].Config = req.Config
        }
 
-       err = checkAggregateInstanceLimits(tx, project, instances, profiles)
+       err = checkRestrictionsAndAggregateLimits(tx, project, instances, 
profiles)
        if err != nil {
                return err
        }
@@ -156,7 +156,7 @@ func AllowProfileUpdate(tx *db.ClusterTx, projectName, 
profileName string, req a
                profiles[i].Config = req.Config
        }
 
-       err = checkAggregateInstanceLimits(tx, project, instances, profiles)
+       err = checkRestrictionsAndAggregateLimits(tx, project, instances, 
profiles)
        if err != nil {
                return err
        }

From 89ef6ab892ab66e333f1e11a5ad514179826ca0c Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanay...@canonical.com>
Date: Fri, 28 Feb 2020 09:35:06 +0000
Subject: [PATCH 07/10] lxd/project: Extract checkAggregateLimits from
 checkRestrictionsAndAggregateLimits

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 lxd/project/permissions.go | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index 7c9b4eded7..d5af664078 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -78,16 +78,26 @@ func checkRestrictionsAndAggregateLimits(tx *db.ClusterTx, 
project *api.Project,
        // across all project instances.
        aggregateKeys := []string{}
        for key := range project.Config {
-               if shared.StringInSlice(key, []string{"limits.memory", 
"limits.processes", "limits.cpu"}) {
+               if shared.StringInSlice(key, allAggregateLimits) {
                        aggregateKeys = append(aggregateKeys, key)
                }
        }
+
        if len(aggregateKeys) == 0 {
                return nil
        }
 
        instances = expandInstancesConfig(instances, profiles)
 
+       err := checkAggregateLimits(project, instances, aggregateKeys)
+       if err != nil {
+               return err
+       }
+
+       return nil
+}
+
+func checkAggregateLimits(project *api.Project, instances []db.Instance, 
aggregateKeys []string) error {
        totals, err := getTotalsAcrossInstances(instances, aggregateKeys)
        if err != nil {
                return err
@@ -105,10 +115,15 @@ func checkRestrictionsAndAggregateLimits(tx 
*db.ClusterTx, project *api.Project,
                                project.Config[key], key, project.Name)
                }
        }
-
        return nil
 }
 
+var allAggregateLimits = []string{
+       "limits.cpu",
+       "limits.memory",
+       "limits.processes",
+}
+
 // AllowInstanceUpdate returns an error if any project-specific limit or
 // restriction is violated when updating an existing instance.
 func AllowInstanceUpdate(tx *db.ClusterTx, projectName, instanceName string, 
req api.InstancePut) error {

From 1d6d91251bcf9b3b9912d34e39b609ebf9ed9064 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanay...@canonical.com>
Date: Fri, 28 Feb 2020 09:56:46 +0000
Subject: [PATCH 08/10] lxd/project: Honor the "restrict.containers.nesting"
 config

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 lxd/project/permissions.go | 72 +++++++++++++++++++++++++++++++++++---
 1 file changed, 67 insertions(+), 5 deletions(-)

diff --git a/lxd/project/permissions.go b/lxd/project/permissions.go
index d5af664078..bfcdad0059 100644
--- a/lxd/project/permissions.go
+++ b/lxd/project/permissions.go
@@ -31,6 +31,7 @@ func AllowInstanceCreation(tx *db.ClusterTx, projectName 
string, req api.Instanc
 
        // Add the instance being created.
        instances = append(instances, db.Instance{
+               Name:     req.Name,
                Profiles: req.Profiles,
                Config:   req.Config,
        })
@@ -83,7 +84,15 @@ func checkRestrictionsAndAggregateLimits(tx *db.ClusterTx, 
project *api.Project,
                }
        }
 
-       if len(aggregateKeys) == 0 {
+       // List of restriction-related keys.
+       restrictionKeys := []string{}
+       for key := range project.Config {
+               if shared.StringInSlice(key, allRestrictions) {
+                       restrictionKeys = append(restrictionKeys, key)
+               }
+       }
+
+       if len(aggregateKeys) == 0 && len(restrictionKeys) == 0 {
                return nil
        }
 
@@ -94,10 +103,19 @@ func checkRestrictionsAndAggregateLimits(tx *db.ClusterTx, 
project *api.Project,
                return err
        }
 
+       err = checkRestrictions(project, instances, restrictionKeys)
+       if err != nil {
+               return err
+       }
+
        return nil
 }
 
 func checkAggregateLimits(project *api.Project, instances []db.Instance, 
aggregateKeys []string) error {
+       if len(aggregateKeys) == 0 {
+               return nil
+       }
+
        totals, err := getTotalsAcrossInstances(instances, aggregateKeys)
        if err != nil {
                return err
@@ -118,12 +136,56 @@ func checkAggregateLimits(project *api.Project, instances 
[]db.Instance, aggrega
        return nil
 }
 
+func checkRestrictions(project *api.Project, instances []db.Instance, 
restrictionKeys []string) error {
+       if len(restrictionKeys) == 0 {
+               return nil
+       }
+
+       containerKeyChecks := map[string]func(value string) error{}
+
+       for _, key := range restrictionKeys {
+               switch key {
+               case "restrict.containers.nesting":
+                       containerKeyChecks["security.nesting"] = func(value 
string) error {
+                               if !shared.IsTrue(value) {
+                                       return nil
+                               }
+                               return fmt.Errorf("Container nesting is 
forbidden")
+                       }
+               }
+       }
+
+       for _, instance := range instances {
+               if instance.Type == instancetype.Container {
+                       for key, value := range instance.Config {
+                               checker, ok := containerKeyChecks[key]
+                               if !ok {
+                                       continue
+                               }
+                               err := checker(value)
+                               if err != nil {
+                                       return errors.Wrapf(
+                                               err,
+                                               "Invalid value %q for config %q 
on instance %q of project %q",
+                                               value, key, instance.Name, 
project.Name)
+                               }
+                       }
+               }
+       }
+
+       return nil
+}
+
 var allAggregateLimits = []string{
        "limits.cpu",
        "limits.memory",
        "limits.processes",
 }
 
+var allRestrictions = []string{
+       "restrict.containers.nesting",
+}
+
 // AllowInstanceUpdate returns an error if any project-specific limit or
 // restriction is violated when updating an existing instance.
 func AllowInstanceUpdate(tx *db.ClusterTx, projectName, instanceName string, 
req api.InstancePut) error {
@@ -277,10 +339,10 @@ func validateAggregateLimit(totals map[string]int64, key, 
value string) error {
        return nil
 }
 
-// Return true if the project has some limits.
-func projectHasLimits(project *api.Project) bool {
+// Return true if the project has some limits or restrictions set.
+func projectHasLimitsOrRestrictions(project *api.Project) bool {
        for k := range project.Config {
-               if strings.HasPrefix(k, "limits.") {
+               if strings.HasPrefix(k, "limits.") || strings.HasPrefix(k, 
"restrict.") {
                        return true
                }
        }
@@ -297,7 +359,7 @@ func fetchProject(tx *db.ClusterTx, projectName string, 
skipIfNoLimits bool) (*a
                return nil, nil, nil, errors.Wrap(err, "Fetch project database 
object")
        }
 
-       if skipIfNoLimits && !projectHasLimits(project) {
+       if skipIfNoLimits && !projectHasLimitsOrRestrictions(project) {
                return nil, nil, nil, nil
        }
 

From e6d2f4b8c7c4e9374a428e38491c0ceb117e0c92 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanay...@canonical.com>
Date: Fri, 28 Feb 2020 09:10:59 +0000
Subject: [PATCH 09/10] api: Add new restrict.* config keys to projects

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 lxd/api_project.go | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/lxd/api_project.go b/lxd/api_project.go
index da215c2004..e736671a45 100644
--- a/lxd/api_project.go
+++ b/lxd/api_project.go
@@ -515,13 +515,14 @@ func projectIsEmpty(project *api.Project) bool {
 
 // Validate the project configuration
 var projectConfigKeys = map[string]func(value string) error{
-       "features.profiles":       shared.IsBool,
-       "features.images":         shared.IsBool,
-       "limits.containers":       shared.IsUint32,
-       "limits.virtual-machines": shared.IsUint32,
-       "limits.memory":           shared.IsSize,
-       "limits.processes":        shared.IsUint32,
-       "limits.cpu":              shared.IsUint32,
+       "features.profiles":           shared.IsBool,
+       "features.images":             shared.IsBool,
+       "limits.containers":           shared.IsUint32,
+       "limits.virtual-machines":     shared.IsUint32,
+       "limits.memory":               shared.IsSize,
+       "limits.processes":            shared.IsUint32,
+       "limits.cpu":                  shared.IsUint32,
+       "restrict.containers.nesting": shared.IsBool,
 }
 
 func projectValidateConfig(config map[string]string) error {

From 522f9dda3f8adf0f678db866bcec5b1b1d92390b Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanay...@canonical.com>
Date: Fri, 28 Feb 2020 10:18:04 +0000
Subject: [PATCH 10/10] test: Add projects restrictions tests

Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com>
---
 test/main.sh            |  1 +
 test/suites/projects.sh | 25 +++++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/test/main.sh b/test/main.sh
index 8c142cdb39..7a56b501b8 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -193,6 +193,7 @@ run_test test_projects_images_default "images from the 
global default project"
 run_test test_projects_storage "projects and storage pools"
 run_test test_projects_network "projects and networks"
 run_test test_projects_limits "projects limits"
+run_test test_projects_restrictions "projects restrictions"
 run_test test_container_devices_disk "container devices - disk"
 run_test test_container_devices_nic_p2p "container devices - nic - p2p"
 run_test test_container_devices_nic_bridged "container devices - nic - bridged"
diff --git a/test/suites/projects.sh b/test/suites/projects.sh
index c8060f2d9a..9980f7bee8 100644
--- a/test/suites/projects.sh
+++ b/test/suites/projects.sh
@@ -625,3 +625,28 @@ test_projects_limits() {
   lxc project switch default
   lxc project delete p1
 }
+
+# Set restrictions on projects.
+test_projects_restrictions() {
+  # Create a project
+  lxc project create p1
+
+  lxc project switch p1
+
+  # Add a root device to the default profile of the project and import an 
image.
+  pool="lxdtest-$(basename "${LXD_DIR}")"
+  lxc profile device add default root disk path="/" pool="${pool}"
+
+  deps/import-busybox --project p1 --alias testimage
+  fingerprint="$(lxc image list -c f --format json | jq -r .[0].fingerprint)"
+
+  # Create a couple of containers in the project.
+  lxc project set p1 restrict.containers.nesting=true
+
+  ! lxc init testimage c1 -c security.nesting=true || false
+
+  lxc image delete testimage
+
+  lxc project switch default
+  lxc project delete p1
+}
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to