mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-02-20 01:28:45 +01:00
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com> Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
This commit is contained in:
1087
pkg/apiclient/project/mocks/ProjectServiceClient.go
generated
Normal file
1087
pkg/apiclient/project/mocks/ProjectServiceClient.go
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -396,8 +396,8 @@ func (proj *AppProject) ProjectPoliciesString() string {
|
||||
return strings.Join(policies, "\n")
|
||||
}
|
||||
|
||||
// IsGroupKindPermitted validates if the given resource group/kind is permitted to be deployed in the project
|
||||
func (proj AppProject) IsGroupKindPermitted(gk schema.GroupKind, namespaced bool) bool {
|
||||
// IsGroupKindNamePermitted validates if the given resource group/kind is permitted to be deployed in the project
|
||||
func (proj AppProject) IsGroupKindNamePermitted(gk schema.GroupKind, name string, namespaced bool) bool {
|
||||
var isWhiteListed, isBlackListed bool
|
||||
res := metav1.GroupKind{Group: gk.Group, Kind: gk.Kind}
|
||||
|
||||
@@ -413,18 +413,18 @@ func (proj AppProject) IsGroupKindPermitted(gk schema.GroupKind, namespaced bool
|
||||
clusterWhitelist := proj.Spec.ClusterResourceWhitelist
|
||||
clusterBlacklist := proj.Spec.ClusterResourceBlacklist
|
||||
|
||||
isWhiteListed = len(clusterWhitelist) != 0 && isResourceInList(res, clusterWhitelist)
|
||||
isBlackListed = len(clusterBlacklist) != 0 && isResourceInList(res, clusterBlacklist)
|
||||
isWhiteListed = len(clusterWhitelist) != 0 && isNamedResourceInList(res, name, clusterWhitelist)
|
||||
isBlackListed = len(clusterBlacklist) != 0 && isNamedResourceInList(res, name, clusterBlacklist)
|
||||
return isWhiteListed && !isBlackListed
|
||||
}
|
||||
|
||||
// IsLiveResourcePermitted returns whether a live resource found in the cluster is permitted by an AppProject
|
||||
func (proj AppProject) IsLiveResourcePermitted(un *unstructured.Unstructured, destCluster *Cluster, projectClusters func(project string) ([]*Cluster, error)) (bool, error) {
|
||||
return proj.IsResourcePermitted(un.GroupVersionKind().GroupKind(), un.GetNamespace(), destCluster, projectClusters)
|
||||
return proj.IsResourcePermitted(un.GroupVersionKind().GroupKind(), un.GetName(), un.GetNamespace(), destCluster, projectClusters)
|
||||
}
|
||||
|
||||
func (proj AppProject) IsResourcePermitted(groupKind schema.GroupKind, namespace string, destCluster *Cluster, projectClusters func(project string) ([]*Cluster, error)) (bool, error) {
|
||||
if !proj.IsGroupKindPermitted(groupKind, namespace != "") {
|
||||
func (proj AppProject) IsResourcePermitted(groupKind schema.GroupKind, name string, namespace string, destCluster *Cluster, projectClusters func(project string) ([]*Cluster, error)) (bool, error) {
|
||||
if !proj.IsGroupKindNamePermitted(groupKind, name, namespace != "") {
|
||||
return false, nil
|
||||
}
|
||||
if namespace != "" {
|
||||
|
||||
2037
pkg/apis/application/v1alpha1/generated.pb.go
generated
2037
pkg/apis/application/v1alpha1/generated.pb.go
generated
File diff suppressed because it is too large
Load Diff
@@ -83,7 +83,7 @@ message AppProjectSpec {
|
||||
repeated ProjectRole roles = 4;
|
||||
|
||||
// ClusterResourceWhitelist contains list of whitelisted cluster level resources
|
||||
repeated .k8s.io.apimachinery.pkg.apis.meta.v1.GroupKind clusterResourceWhitelist = 5;
|
||||
repeated ClusterResourceRestrictionItem clusterResourceWhitelist = 5;
|
||||
|
||||
// NamespaceResourceBlacklist contains list of blacklisted namespace level resources
|
||||
repeated .k8s.io.apimachinery.pkg.apis.meta.v1.GroupKind namespaceResourceBlacklist = 6;
|
||||
@@ -101,7 +101,7 @@ message AppProjectSpec {
|
||||
repeated SignatureKey signatureKeys = 10;
|
||||
|
||||
// ClusterResourceBlacklist contains list of blacklisted cluster level resources
|
||||
repeated .k8s.io.apimachinery.pkg.apis.meta.v1.GroupKind clusterResourceBlacklist = 11;
|
||||
repeated ClusterResourceRestrictionItem clusterResourceBlacklist = 11;
|
||||
|
||||
// SourceNamespaces defines the namespaces application resources are allowed to be created in
|
||||
repeated string sourceNamespaces = 12;
|
||||
@@ -936,6 +936,17 @@ message ClusterList {
|
||||
repeated Cluster items = 2;
|
||||
}
|
||||
|
||||
// ClusterResourceRestrictionItem is a cluster resource that is restricted by the project's whitelist or blacklist
|
||||
message ClusterResourceRestrictionItem {
|
||||
optional string group = 1;
|
||||
|
||||
optional string kind = 2;
|
||||
|
||||
// Name is the name of the restricted resource. Glob patterns using Go's filepath.Match syntax are supported.
|
||||
// Unlike the group and kind fields, if no name is specified, all resources of the specified group/kind are matched.
|
||||
optional string name = 3;
|
||||
}
|
||||
|
||||
// Command holds binary path and arguments list
|
||||
message Command {
|
||||
repeated string command = 1;
|
||||
|
||||
@@ -2707,7 +2707,7 @@ type AppProjectSpec struct {
|
||||
// Roles are user defined RBAC roles associated with this project
|
||||
Roles []ProjectRole `json:"roles,omitempty" protobuf:"bytes,4,rep,name=roles"`
|
||||
// ClusterResourceWhitelist contains list of whitelisted cluster level resources
|
||||
ClusterResourceWhitelist []metav1.GroupKind `json:"clusterResourceWhitelist,omitempty" protobuf:"bytes,5,opt,name=clusterResourceWhitelist"`
|
||||
ClusterResourceWhitelist []ClusterResourceRestrictionItem `json:"clusterResourceWhitelist,omitempty" protobuf:"bytes,5,opt,name=clusterResourceWhitelist"`
|
||||
// NamespaceResourceBlacklist contains list of blacklisted namespace level resources
|
||||
NamespaceResourceBlacklist []metav1.GroupKind `json:"namespaceResourceBlacklist,omitempty" protobuf:"bytes,6,opt,name=namespaceResourceBlacklist"`
|
||||
// OrphanedResources specifies if controller should monitor orphaned resources of apps in this project
|
||||
@@ -2719,7 +2719,7 @@ type AppProjectSpec struct {
|
||||
// SignatureKeys contains a list of PGP key IDs that commits in Git must be signed with in order to be allowed for sync
|
||||
SignatureKeys []SignatureKey `json:"signatureKeys,omitempty" protobuf:"bytes,10,opt,name=signatureKeys"`
|
||||
// ClusterResourceBlacklist contains list of blacklisted cluster level resources
|
||||
ClusterResourceBlacklist []metav1.GroupKind `json:"clusterResourceBlacklist,omitempty" protobuf:"bytes,11,opt,name=clusterResourceBlacklist"`
|
||||
ClusterResourceBlacklist []ClusterResourceRestrictionItem `json:"clusterResourceBlacklist,omitempty" protobuf:"bytes,11,opt,name=clusterResourceBlacklist"`
|
||||
// SourceNamespaces defines the namespaces application resources are allowed to be created in
|
||||
SourceNamespaces []string `json:"sourceNamespaces,omitempty" protobuf:"bytes,12,opt,name=sourceNamespaces"`
|
||||
// PermitOnlyProjectScopedClusters determines whether destinations can only reference clusters which are project-scoped
|
||||
@@ -2728,6 +2728,15 @@ type AppProjectSpec struct {
|
||||
DestinationServiceAccounts []ApplicationDestinationServiceAccount `json:"destinationServiceAccounts,omitempty" protobuf:"bytes,14,name=destinationServiceAccounts"`
|
||||
}
|
||||
|
||||
// ClusterResourceRestrictionItem is a cluster resource that is restricted by the project's whitelist or blacklist
|
||||
type ClusterResourceRestrictionItem struct {
|
||||
Group string `json:"group" protobuf:"bytes,1,opt,name=group"`
|
||||
Kind string `json:"kind" protobuf:"bytes,2,opt,name=kind"`
|
||||
// Name is the name of the restricted resource. Glob patterns using Go's filepath.Match syntax are supported.
|
||||
// Unlike the group and kind fields, if no name is specified, all resources of the specified group/kind are matched.
|
||||
Name string `json:"name,omitempty" protobuf:"bytes,3,opt,name=name"`
|
||||
}
|
||||
|
||||
// SyncWindows is a collection of sync windows in this project
|
||||
type SyncWindows []*SyncWindow
|
||||
|
||||
@@ -3532,6 +3541,28 @@ func isResourceInList(res metav1.GroupKind, list []metav1.GroupKind) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func isNamedResourceInList(res metav1.GroupKind, name string, list []ClusterResourceRestrictionItem) bool {
|
||||
for _, item := range list {
|
||||
ok, err := filepath.Match(item.Kind, res.Kind)
|
||||
if !ok || err != nil {
|
||||
continue
|
||||
}
|
||||
ok, err = filepath.Match(item.Group, res.Group)
|
||||
if !ok || err != nil {
|
||||
continue
|
||||
}
|
||||
if item.Name == "" {
|
||||
return true
|
||||
}
|
||||
ok, err = filepath.Match(item.Name, name)
|
||||
if !ok || err != nil {
|
||||
continue
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// getFinalizerIndex returns finalizer index in the list of object finalizers or -1 if finalizer does not exist
|
||||
func getFinalizerIndex(meta metav1.ObjectMeta, name string) int {
|
||||
for i, finalizer := range meta.Finalizers {
|
||||
|
||||
@@ -513,8 +513,8 @@ func TestAppProject_IsGroupKindPermitted(t *testing.T) {
|
||||
NamespaceResourceBlacklist: []metav1.GroupKind{{Group: "apps", Kind: "Deployment"}},
|
||||
},
|
||||
}
|
||||
assert.False(t, proj.IsGroupKindPermitted(schema.GroupKind{Group: "apps", Kind: "ReplicaSet"}, true))
|
||||
assert.False(t, proj.IsGroupKindPermitted(schema.GroupKind{Group: "apps", Kind: "Deployment"}, true))
|
||||
assert.False(t, proj.IsGroupKindNamePermitted(schema.GroupKind{Group: "apps", Kind: "ReplicaSet"}, "", true))
|
||||
assert.False(t, proj.IsGroupKindNamePermitted(schema.GroupKind{Group: "apps", Kind: "Deployment"}, "", true))
|
||||
|
||||
proj2 := AppProject{
|
||||
Spec: AppProjectSpec{
|
||||
@@ -522,39 +522,47 @@ func TestAppProject_IsGroupKindPermitted(t *testing.T) {
|
||||
NamespaceResourceBlacklist: []metav1.GroupKind{{Group: "apps", Kind: "Deployment"}},
|
||||
},
|
||||
}
|
||||
assert.True(t, proj2.IsGroupKindPermitted(schema.GroupKind{Group: "apps", Kind: "ReplicaSet"}, true))
|
||||
assert.False(t, proj2.IsGroupKindPermitted(schema.GroupKind{Group: "apps", Kind: "Action"}, true))
|
||||
assert.True(t, proj2.IsGroupKindNamePermitted(schema.GroupKind{Group: "apps", Kind: "ReplicaSet"}, "", true))
|
||||
assert.False(t, proj2.IsGroupKindNamePermitted(schema.GroupKind{Group: "apps", Kind: "Action"}, "", true))
|
||||
|
||||
proj3 := AppProject{
|
||||
Spec: AppProjectSpec{
|
||||
ClusterResourceBlacklist: []metav1.GroupKind{{Group: "", Kind: "Namespace"}},
|
||||
ClusterResourceBlacklist: []ClusterResourceRestrictionItem{{Group: "", Kind: "Namespace"}},
|
||||
},
|
||||
}
|
||||
assert.False(t, proj3.IsGroupKindPermitted(schema.GroupKind{Group: "", Kind: "Namespace"}, false))
|
||||
assert.False(t, proj3.IsGroupKindNamePermitted(schema.GroupKind{Group: "", Kind: "Namespace"}, "", false))
|
||||
|
||||
proj4 := AppProject{
|
||||
Spec: AppProjectSpec{
|
||||
ClusterResourceWhitelist: []metav1.GroupKind{{Group: "*", Kind: "*"}},
|
||||
ClusterResourceBlacklist: []metav1.GroupKind{{Group: "*", Kind: "*"}},
|
||||
ClusterResourceWhitelist: []ClusterResourceRestrictionItem{{Group: "*", Kind: "*"}},
|
||||
ClusterResourceBlacklist: []ClusterResourceRestrictionItem{{Group: "*", Kind: "*"}},
|
||||
},
|
||||
}
|
||||
assert.False(t, proj4.IsGroupKindPermitted(schema.GroupKind{Group: "", Kind: "Namespace"}, false))
|
||||
assert.True(t, proj4.IsGroupKindPermitted(schema.GroupKind{Group: "apps", Kind: "Action"}, true))
|
||||
assert.False(t, proj4.IsGroupKindNamePermitted(schema.GroupKind{Group: "", Kind: "Namespace"}, "", false))
|
||||
assert.True(t, proj4.IsGroupKindNamePermitted(schema.GroupKind{Group: "apps", Kind: "Action"}, "", true))
|
||||
|
||||
proj5 := AppProject{
|
||||
Spec: AppProjectSpec{
|
||||
ClusterResourceWhitelist: []metav1.GroupKind{},
|
||||
ClusterResourceWhitelist: []ClusterResourceRestrictionItem{},
|
||||
NamespaceResourceWhitelist: []metav1.GroupKind{{Group: "*", Kind: "*"}},
|
||||
},
|
||||
}
|
||||
assert.False(t, proj5.IsGroupKindPermitted(schema.GroupKind{Group: "", Kind: "Namespace"}, false))
|
||||
assert.True(t, proj5.IsGroupKindPermitted(schema.GroupKind{Group: "apps", Kind: "Action"}, true))
|
||||
assert.False(t, proj5.IsGroupKindNamePermitted(schema.GroupKind{Group: "", Kind: "Namespace"}, "", false))
|
||||
assert.True(t, proj5.IsGroupKindNamePermitted(schema.GroupKind{Group: "apps", Kind: "Action"}, "", true))
|
||||
|
||||
proj6 := AppProject{
|
||||
Spec: AppProjectSpec{},
|
||||
}
|
||||
assert.False(t, proj6.IsGroupKindPermitted(schema.GroupKind{Group: "", Kind: "Namespace"}, false))
|
||||
assert.True(t, proj6.IsGroupKindPermitted(schema.GroupKind{Group: "apps", Kind: "Action"}, true))
|
||||
assert.False(t, proj6.IsGroupKindNamePermitted(schema.GroupKind{Group: "", Kind: "Namespace"}, "", false))
|
||||
assert.True(t, proj6.IsGroupKindNamePermitted(schema.GroupKind{Group: "apps", Kind: "Action"}, "", true))
|
||||
|
||||
proj7 := AppProject{
|
||||
Spec: AppProjectSpec{
|
||||
ClusterResourceWhitelist: []ClusterResourceRestrictionItem{{Group: "", Kind: "Namespace", Name: "team1-*"}},
|
||||
},
|
||||
}
|
||||
assert.False(t, proj7.IsGroupKindNamePermitted(schema.GroupKind{Group: "", Kind: "Namespace"}, "other-namespace", false))
|
||||
assert.True(t, proj7.IsGroupKindNamePermitted(schema.GroupKind{Group: "", Kind: "Namespace"}, "team1-namespace", false))
|
||||
}
|
||||
|
||||
func TestAppProject_GetRoleByName(t *testing.T) {
|
||||
|
||||
@@ -145,7 +145,7 @@ func (in *AppProjectSpec) DeepCopyInto(out *AppProjectSpec) {
|
||||
}
|
||||
if in.ClusterResourceWhitelist != nil {
|
||||
in, out := &in.ClusterResourceWhitelist, &out.ClusterResourceWhitelist
|
||||
*out = make([]v1.GroupKind, len(*in))
|
||||
*out = make([]ClusterResourceRestrictionItem, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.NamespaceResourceBlacklist != nil {
|
||||
@@ -181,7 +181,7 @@ func (in *AppProjectSpec) DeepCopyInto(out *AppProjectSpec) {
|
||||
}
|
||||
if in.ClusterResourceBlacklist != nil {
|
||||
in, out := &in.ClusterResourceBlacklist, &out.ClusterResourceBlacklist
|
||||
*out = make([]v1.GroupKind, len(*in))
|
||||
*out = make([]ClusterResourceRestrictionItem, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.SourceNamespaces != nil {
|
||||
@@ -1800,6 +1800,22 @@ func (in *ClusterList) DeepCopy() *ClusterList {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ClusterResourceRestrictionItem) DeepCopyInto(out *ClusterResourceRestrictionItem) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterResourceRestrictionItem.
|
||||
func (in *ClusterResourceRestrictionItem) DeepCopy() *ClusterResourceRestrictionItem {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClusterResourceRestrictionItem)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Command) DeepCopyInto(out *Command) {
|
||||
*out = *in
|
||||
|
||||
Reference in New Issue
Block a user