diff --git a/cmd/argocd-server/commands/argocd_server.go b/cmd/argocd-server/commands/argocd_server.go index eea346eaed03d..0d5bbc244e5f8 100644 --- a/cmd/argocd-server/commands/argocd_server.go +++ b/cmd/argocd-server/commands/argocd_server.go @@ -42,34 +42,35 @@ var ( // NewCommand returns a new instance of an argocd command func NewCommand() *cobra.Command { var ( - redisClient *redis.Client - insecure bool - listenHost string - listenPort int - metricsHost string - metricsPort int - otlpAddress string - otlpAttrs []string - glogLevel int - clientConfig clientcmd.ClientConfig - repoServerTimeoutSeconds int - baseHRef string - rootPath string - repoServerAddress string - dexServerAddress string - disableAuth bool - enableGZip bool - tlsConfigCustomizerSrc func() (tls.ConfigCustomizer, error) - cacheSrc func() (*servercache.Cache, error) - frameOptions string - contentSecurityPolicy string - repoServerPlaintext bool - repoServerStrictTLS bool - dexServerPlaintext bool - dexServerStrictTLS bool - staticAssetsDir string - applicationNamespaces []string - enableProxyExtension bool + redisClient *redis.Client + insecure bool + listenHost string + listenPort int + metricsHost string + metricsPort int + otlpAddress string + otlpAttrs []string + glogLevel int + clientConfig clientcmd.ClientConfig + repoServerTimeoutSeconds int + baseHRef string + rootPath string + repoServerAddress string + dexServerAddress string + disableAuth bool + enableGZip bool + tlsConfigCustomizerSrc func() (tls.ConfigCustomizer, error) + cacheSrc func() (*servercache.Cache, error) + frameOptions string + contentSecurityPolicy string + repoServerPlaintext bool + repoServerStrictTLS bool + dexServerPlaintext bool + dexServerStrictTLS bool + staticAssetsDir string + applicationNamespaces []string + enableProxyExtension bool + disableDefaultProjectCreation bool ) var command = &cobra.Command{ Use: cliName, @@ -163,29 +164,30 @@ func NewCommand() *cobra.Command { } argoCDOpts := server.ArgoCDServerOpts{ - Insecure: insecure, - ListenPort: listenPort, - ListenHost: listenHost, - MetricsPort: metricsPort, - MetricsHost: metricsHost, - Namespace: namespace, - BaseHRef: baseHRef, - RootPath: rootPath, - KubeClientset: kubeclientset, - AppClientset: appClientSet, - RepoClientset: repoclientset, - DexServerAddr: dexServerAddress, - DexTLSConfig: dexTlsConfig, - DisableAuth: disableAuth, - EnableGZip: enableGZip, - TLSConfigCustomizer: tlsConfigCustomizer, - Cache: cache, - XFrameOptions: frameOptions, - ContentSecurityPolicy: contentSecurityPolicy, - RedisClient: redisClient, - StaticAssetsDir: staticAssetsDir, - ApplicationNamespaces: applicationNamespaces, - EnableProxyExtension: enableProxyExtension, + Insecure: insecure, + ListenPort: listenPort, + ListenHost: listenHost, + MetricsPort: metricsPort, + MetricsHost: metricsHost, + Namespace: namespace, + BaseHRef: baseHRef, + RootPath: rootPath, + KubeClientset: kubeclientset, + AppClientset: appClientSet, + RepoClientset: repoclientset, + DexServerAddr: dexServerAddress, + DexTLSConfig: dexTlsConfig, + DisableAuth: disableAuth, + EnableGZip: enableGZip, + TLSConfigCustomizer: tlsConfigCustomizer, + Cache: cache, + XFrameOptions: frameOptions, + ContentSecurityPolicy: contentSecurityPolicy, + RedisClient: redisClient, + StaticAssetsDir: staticAssetsDir, + ApplicationNamespaces: applicationNamespaces, + EnableProxyExtension: enableProxyExtension, + DisableDefaultProjectCreation: disableDefaultProjectCreation, } stats.RegisterStackDumper() @@ -241,6 +243,7 @@ func NewCommand() *cobra.Command { command.Flags().BoolVar(&dexServerStrictTLS, "dex-server-strict-tls", env.ParseBoolFromEnv("ARGOCD_SERVER_DEX_SERVER_STRICT_TLS", false), "Perform strict validation of TLS certificates when connecting to dex server") command.Flags().StringSliceVar(&applicationNamespaces, "application-namespaces", env.StringsFromEnv("ARGOCD_APPLICATION_NAMESPACES", []string{}, ","), "List of additional namespaces where application resources can be managed in") command.Flags().BoolVar(&enableProxyExtension, "enable-proxy-extension", env.ParseBoolFromEnv("ARGOCD_SERVER_ENABLE_PROXY_EXTENSION", false), "Enable Proxy Extension feature") + command.Flags().BoolVar(&disableDefaultProjectCreation, "disable-default-project-creation", env.ParseBoolFromEnv("ARGOCD_DISABLE_DEFAULT_PROJECT_CREATION", false), "Disable default project creation") tlsConfigCustomizerSrc = tls.AddTLSFlagsToCmd(command) cacheSrc = servercache.AddCacheFlagsToCmd(command, func(client *redis.Client) { redisClient = client diff --git a/cmd/argocd/commands/headless/headless.go b/cmd/argocd/commands/headless/headless.go index bf893ef76ecbe..d0885990fe747 100644 --- a/cmd/argocd/commands/headless/headless.go +++ b/cmd/argocd/commands/headless/headless.go @@ -210,18 +210,19 @@ func StartLocalServer(ctx context.Context, clientOpts *apiclient.ClientOptions, } appstateCache := appstatecache.NewCache(cache.NewCache(&forwardCacheClient{namespace: namespace, context: ctxStr, compression: compression, redisHaProxyName: clientOpts.RedisHaProxyName, redisName: clientOpts.RedisName}), time.Hour) srv := server.NewServer(ctx, server.ArgoCDServerOpts{ - EnableGZip: false, - Namespace: namespace, - ListenPort: *port, - AppClientset: appClientset, - DisableAuth: true, - RedisClient: redis.NewClient(&redis.Options{Addr: mr.Addr()}), - Cache: servercache.NewCache(appstateCache, 0, 0, 0), - KubeClientset: kubeClientset, - Insecure: true, - ListenHost: *address, - RepoClientset: &forwardRepoClientset{namespace: namespace, context: ctxStr, repoServerName: clientOpts.RepoServerName}, - EnableProxyExtension: false, + EnableGZip: false, + Namespace: namespace, + ListenPort: *port, + AppClientset: appClientset, + DisableAuth: true, + RedisClient: redis.NewClient(&redis.Options{Addr: mr.Addr()}), + Cache: servercache.NewCache(appstateCache, 0, 0, 0), + KubeClientset: kubeClientset, + Insecure: true, + ListenHost: *address, + RepoClientset: &forwardRepoClientset{namespace: namespace, context: ctxStr, repoServerName: clientOpts.RepoServerName}, + EnableProxyExtension: false, + DisableDefaultProjectCreation: true, }) srv.Init(ctx) diff --git a/docs/user-guide/projects.md b/docs/user-guide/projects.md index 0ed79ede623d5..65ce39c5de160 100644 --- a/docs/user-guide/projects.md +++ b/docs/user-guide/projects.md @@ -27,6 +27,8 @@ spec: kind: '*' ``` +To disable automatic creation of the default project, set the environment variable ARGOCD_DISABLE_DEFAULT_PROJECT_CREATION=true for the argocd-server, or use the --disable-default-project-creation command line flag. + ### Creating Projects Additional projects can be created to give separate teams different levels of access to namespaces. diff --git a/server/server.go b/server/server.go index 4fbae9da4682c..f73e969a587f0 100644 --- a/server/server.go +++ b/server/server.go @@ -196,33 +196,37 @@ type ArgoCDServer struct { } type ArgoCDServerOpts struct { - DisableAuth bool - EnableGZip bool - Insecure bool - StaticAssetsDir string - ListenPort int - ListenHost string - MetricsPort int - MetricsHost string - Namespace string - DexServerAddr string - DexTLSConfig *dexutil.DexTLSConfig - BaseHRef string - RootPath string - KubeClientset kubernetes.Interface - AppClientset appclientset.Interface - RepoClientset repoapiclient.Clientset - Cache *servercache.Cache - RedisClient *redis.Client - TLSConfigCustomizer tlsutil.ConfigCustomizer - XFrameOptions string - ContentSecurityPolicy string - ApplicationNamespaces []string - EnableProxyExtension bool + DisableAuth bool + EnableGZip bool + Insecure bool + StaticAssetsDir string + ListenPort int + ListenHost string + MetricsPort int + MetricsHost string + Namespace string + DexServerAddr string + DexTLSConfig *dexutil.DexTLSConfig + BaseHRef string + RootPath string + KubeClientset kubernetes.Interface + AppClientset appclientset.Interface + RepoClientset repoapiclient.Clientset + Cache *servercache.Cache + RedisClient *redis.Client + TLSConfigCustomizer tlsutil.ConfigCustomizer + XFrameOptions string + ContentSecurityPolicy string + ApplicationNamespaces []string + EnableProxyExtension bool + DisableDefaultProjectCreation bool } -// initializeDefaultProject creates the default project if it does not already exist +// initializeDefaultProject creates the default project if it does not already exist and the feature is not disabled. func initializeDefaultProject(opts ArgoCDServerOpts) error { + if opts.DisableDefaultProjectCreation { + return nil + } defaultProj := &v1alpha1.AppProject{ ObjectMeta: metav1.ObjectMeta{Name: v1alpha1.DefaultAppProjectName, Namespace: opts.Namespace}, Spec: v1alpha1.AppProjectSpec{ diff --git a/server/server_test.go b/server/server_test.go index 303f938871f38..1af6e30fbc4a9 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -1008,10 +1008,11 @@ func TestTranslateGrpcCookieHeader(t *testing.T) { func TestInitializeDefaultProject_ProjectDoesNotExist(t *testing.T) { argoCDOpts := ArgoCDServerOpts{ - Namespace: test.FakeArgoCDNamespace, - KubeClientset: fake.NewSimpleClientset(test.NewFakeConfigMap(), test.NewFakeSecret()), - AppClientset: apps.NewSimpleClientset(), - RepoClientset: &mocks.Clientset{RepoServerServiceClient: &mocks.RepoServerServiceClient{}}, + Namespace: test.FakeArgoCDNamespace, + KubeClientset: fake.NewSimpleClientset(test.NewFakeConfigMap(), test.NewFakeSecret()), + AppClientset: apps.NewSimpleClientset(), + RepoClientset: &mocks.Clientset{RepoServerServiceClient: &mocks.RepoServerServiceClient{}}, + DisableDefaultProjectCreation: false, } err := initializeDefaultProject(argoCDOpts) @@ -1067,6 +1068,61 @@ func TestInitializeDefaultProject_ProjectAlreadyInitialized(t *testing.T) { assert.Equal(t, proj.Spec, existingDefaultProject.Spec) } +func TestInitializeDefaultProjectWithFeatureDisabled_ProjectShouldNotExist(t *testing.T) { + argoCDOpts := ArgoCDServerOpts{ + Namespace: test.FakeArgoCDNamespace, + KubeClientset: fake.NewSimpleClientset(test.NewFakeConfigMap(), test.NewFakeSecret()), + AppClientset: apps.NewSimpleClientset(), + RepoClientset: &mocks.Clientset{RepoServerServiceClient: &mocks.RepoServerServiceClient{}}, + DisableDefaultProjectCreation: true, + } + + err := initializeDefaultProject(argoCDOpts) + if !assert.NoError(t, err) { + return + } + + _, err = argoCDOpts.AppClientset.ArgoprojV1alpha1(). + AppProjects(test.FakeArgoCDNamespace).Get(context.Background(), v1alpha1.DefaultAppProjectName, metav1.GetOptions{}) + + assert.Error(t, err) +} + +func TestInitializeDefaultProjectWithFeatureDisabled_ProjectAlreadyInitialized(t *testing.T) { + existingDefaultProject := v1alpha1.AppProject{ + ObjectMeta: metav1.ObjectMeta{ + Name: v1alpha1.DefaultAppProjectName, + Namespace: test.FakeArgoCDNamespace, + }, + Spec: v1alpha1.AppProjectSpec{ + SourceRepos: []string{"some repo"}, + Destinations: []v1alpha1.ApplicationDestination{{Server: "some cluster", Namespace: "*"}}, + }, + } + + argoCDOpts := ArgoCDServerOpts{ + Namespace: test.FakeArgoCDNamespace, + KubeClientset: fake.NewSimpleClientset(test.NewFakeConfigMap(), test.NewFakeSecret()), + AppClientset: apps.NewSimpleClientset(&existingDefaultProject), + RepoClientset: &mocks.Clientset{RepoServerServiceClient: &mocks.RepoServerServiceClient{}}, + DisableDefaultProjectCreation: true, + } + + err := initializeDefaultProject(argoCDOpts) + if !assert.NoError(t, err) { + return + } + + proj, err := argoCDOpts.AppClientset.ArgoprojV1alpha1(). + AppProjects(test.FakeArgoCDNamespace).Get(context.Background(), v1alpha1.DefaultAppProjectName, metav1.GetOptions{}) + + if !assert.NoError(t, err) { + return + } + + assert.Equal(t, proj.Spec, existingDefaultProject.Spec) +} + func TestOIDCConfigChangeDetection_SecretsChanged(t *testing.T) { //Given rawOIDCConfig, err := yaml.Marshal(&settings_util.OIDCConfig{