Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: rbac validate command can now take either namespace or policy-file #15543

Merged
merged 12 commits into from
Oct 30, 2023
50 changes: 42 additions & 8 deletions cmd/argocd/commands/admin/settings_rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ argocd admin settings rbac can someuser create application 'default/app' --defau
}
},
}

clientConfig = cli.AddKubectlFlagsToCmd(command)
command.Flags().StringVar(&policyFile, "policy-file", "", "path to the policy file to use")
command.Flags().StringVar(&defaultRole, "default-role", "", "name of the default role to use")
Expand All @@ -202,24 +201,55 @@ argocd admin settings rbac can someuser create application 'default/app' --defau
// NewRBACValidateCommand returns a new rbac validate command
func NewRBACValidateCommand() *cobra.Command {
var (
policyFile string
policyFile string
namespace string
clientConfig clientcmd.ClientConfig
)

var command = &cobra.Command{
Use: "validate --policy-file=POLICYFILE",
Use: "validate [--policy-file POLICYFILE] [--namespace NAMESPACE]",
Short: "Validate RBAC policy",
Long: `
Validates an RBAC policy for being syntactically correct. The policy must be
a local file, and in either CSV or K8s ConfigMap format.
a local file or a K8s ConfigMap in the provided namespace, and in either CSV or K8s ConfigMap format.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we are updating the command, can we add an example as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding one, let me know if the wording looks fine

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wording looks good! Thanks!

`,
Example: `
# Check whether a given policy file is valid using a local policy.csv file.
argocd admin settings rbac validate --policy-file policy.csv

# Policy file can also be K8s config map with data keys like argocd-rbac-cm,
# i.e. 'policy.csv' and (optionally) 'policy.default'
argocd admin settings rbac validate --policy-file argocd-rbac-cm.yaml

# If --policy-file is not given, and instead --namespace is giventhe ConfigMap 'argocd-rbac-cm'
# from K8s is used.
argocd admin settings rbac validate --namespace argocd

# Either --policy-file or --namespace must be given.
`,
Run: func(c *cobra.Command, args []string) {
ctx := c.Context()

if policyFile == "" {
if len(args) > 0 {
c.HelpFunc()(c, args)
log.Fatalf("Please specify policy to validate using --policy-file")
log.Fatalf("too many arguments")
}

if (namespace == "" && policyFile == "") || (namespace != "" && policyFile != "") {
c.HelpFunc()(c, args)
log.Fatalf("please provide exactly one of --policy-file or --namespace")
}
userPolicy, _, _ := getPolicy(ctx, policyFile, nil, "")

restConfig, err := clientConfig.ClientConfig()
if err != nil {
log.Fatalf("could not get config to create k8s client: %v", err)
}
realClientset, err := kubernetes.NewForConfig(restConfig)
if err != nil {
log.Fatalf("could not create k8s client: %v", err)
}

userPolicy, _, _ := getPolicy(ctx, policyFile, realClientset, namespace)
if userPolicy != "" {
if err := rbac.ValidatePolicy(userPolicy); err == nil {
fmt.Printf("Policy is valid.\n")
Expand All @@ -228,11 +258,15 @@ a local file, and in either CSV or K8s ConfigMap format.
fmt.Printf("Policy is invalid: %v\n", err)
os.Exit(1)
}
} else {
log.Fatalf("Policy is empty or could not be loaded.")
}
},
}

clientConfig = cli.AddKubectlFlagsToCmd(command)
command.Flags().StringVar(&policyFile, "policy-file", "", "path to the policy file to use")
command.Flags().StringVar(&namespace, "namespace", "", "namespace to get argo rbac configmap from")

return command
}

Expand Down
47 changes: 45 additions & 2 deletions cmd/argocd/commands/admin/settings_rbac_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,42 @@ import (
"os"
"testing"

"github.com/argoproj/argo-cd/v2/util/assets"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"

"github.com/argoproj/argo-cd/v2/util/assets"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)

type FakeClientConfig struct {
clientConfig clientcmd.ClientConfig
}

func NewFakeClientConfig(clientConfig clientcmd.ClientConfig) *FakeClientConfig {
return &FakeClientConfig{clientConfig: clientConfig}
}

func (f *FakeClientConfig) RawConfig() (clientcmdapi.Config, error) {
config, err := f.clientConfig.RawConfig()
return config, err
}

func (f *FakeClientConfig) ClientConfig() (*restclient.Config, error) {
return f.clientConfig.ClientConfig()
}

func (f *FakeClientConfig) Namespace() (string, bool, error) {
return f.clientConfig.Namespace()
}

func (f *FakeClientConfig) ConfigAccess() clientcmd.ConfigAccess {
return nil
}

func Test_isValidRBACAction(t *testing.T) {
for k := range validRBACActions {
t.Run(k, func(t *testing.T) {
Expand Down Expand Up @@ -200,3 +227,19 @@ p, role:, certificates, get, .*, allow`
require.True(t, ok)
})
}

func TestNewRBACCanCommand(t *testing.T) {
command := NewRBACCanCommand()

require.NotNil(t, command)
assert.Equal(t, "can", command.Name())
assert.Equal(t, "Check RBAC permissions for a role or subject", command.Short)
}

func TestNewRBACValidateCommand(t *testing.T) {
command := NewRBACValidateCommand()

require.NotNil(t, command)
assert.Equal(t, "validate", command.Name())
assert.Equal(t, "Validate RBAC policy", command.Short)
}
67 changes: 43 additions & 24 deletions docs/user-guide/commands/argocd_admin_settings_rbac_validate.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,68 +8,87 @@ Validate RBAC policy


Validates an RBAC policy for being syntactically correct. The policy must be
a local file, and in either CSV or K8s ConfigMap format.
a local file or a K8s ConfigMap in the provided namespace, and in either CSV or K8s ConfigMap format.


```
argocd admin settings rbac validate --policy-file=POLICYFILE [flags]
argocd admin settings rbac validate [--policy-file POLICYFILE] [--namespace NAMESPACE] [flags]
```

### Examples

```
# Check whether a given policy file is valid using a local policy.csv file.
argocd admin settings rbac validate --policy-file policy.csv
# Policy file can also be K8s config map with data keys like argocd-rbac-cm,
# i.e. 'policy.csv' and (optionally) 'policy.default'
argocd admin settings rbac validate --policy-file argocd-rbac-cm.yaml
# If --policy-file is not given, and instead --namespace is giventhe ConfigMap 'argocd-rbac-cm'
# from K8s is used.
argocd admin settings rbac validate --namespace argocd
# Either --policy-file or --namespace must be given.
```

### Options

```
-h, --help help for validate
--policy-file string path to the policy file to use
--as string Username to impersonate for the operation
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
--disable-compression If true, opt-out of response compression for all requests to the server
-h, --help help for validate
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to a kube config. Only required if out-of-cluster
--namespace string namespace to get argo rbac configmap from
--password string Password for basic authentication to the API server
--policy-file string path to the policy file to use
--proxy-url string If provided, this URL will be used to connect via proxy
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
--server string The address and port of the Kubernetes API server
--tls-server-name string If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used.
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
--username string Username for basic authentication to the API server
```

### Options inherited from parent commands

```
--argocd-cm-path string Path to local argocd-cm.yaml file
--argocd-secret-path string Path to local argocd-secret.yaml file
--as string Username to impersonate for the operation
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--as-uid string UID to impersonate for the operation
--auth-token string Authentication token
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-crt string Client certificate file
--client-crt-key string Client certificate key file
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--config string Path to Argo CD config (default "/home/user/.config/argocd/config")
--context string The name of the kubeconfig context to use
--controller-name string Name of the Argo CD Application controller; set this or the ARGOCD_APPLICATION_CONTROLLER_NAME environment variable when the controller's name label differs from the default, for example when installing via the Helm chart (default "argocd-application-controller")
--core If set to true then CLI talks directly to Kubernetes instead of talking to Argo CD API server
--disable-compression If true, opt-out of response compression for all requests to the server
--grpc-web Enables gRPC-web protocol. Useful if Argo CD server is behind proxy which does not support HTTP2.
--grpc-web-root-path string Enables gRPC-web protocol. Useful if Argo CD server is behind proxy which does not support HTTP2. Set web root.
-H, --header strings Sets additional header to all requests made by Argo CD CLI. (Can be repeated multiple times to add multiple headers, also supports comma separated headers)
--http-retry-max int Maximum number of retries to establish http connection to Argo CD server
--insecure Skip server certificate and domain verification
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kube-context string Directs the command to the given kube-context
--kubeconfig string Path to a kube config. Only required if out-of-cluster
--load-cluster-settings Indicates that config map and secret should be loaded from cluster unless local file path is provided
--logformat string Set the logging format. One of: text|json (default "text")
--loglevel string Set the logging level. One of: debug|info|warn|error (default "info")
-n, --namespace string If present, the namespace scope for this CLI request
--password string Password for basic authentication to the API server
--plaintext Disable TLS
--port-forward Connect to a random argocd-server port using port forwarding
--port-forward-namespace string Namespace name which should be used for port forwarding
--proxy-url string If provided, this URL will be used to connect via proxy
--redis-haproxy-name string Name of the Redis HA Proxy; set this or the ARGOCD_REDIS_HAPROXY_NAME environment variable when the HA Proxy's name label differs from the default, for example when installing via the Helm chart (default "argocd-redis-ha-haproxy")
--redis-name string Name of the Redis deployment; set this or the ARGOCD_REDIS_NAME environment variable when the Redis's name label differs from the default, for example when installing via the Helm chart (default "argocd-redis")
--repo-server-name string Name of the Argo CD Repo server; set this or the ARGOCD_REPO_SERVER_NAME environment variable when the server's name label differs from the default, for example when installing via the Helm chart (default "argocd-repo-server")
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
--server string The address and port of the Kubernetes API server
--server-crt string Server certificate file
--server-name string Name of the Argo CD API server; set this or the ARGOCD_SERVER_NAME environment variable when the server's name label differs from the default, for example when installing via the Helm chart (default "argocd-server")
--tls-server-name string If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used.
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
--username string Username for basic authentication to the API server
```

### SEE ALSO
Expand Down
Loading