Skip to content

Commit

Permalink
fix: rbac validate command can now take either namespace or policy-fi…
Browse files Browse the repository at this point in the history
…le (argoproj#15543)

* fix: rbac validate command can now take either namespace or policy-file as arg

Signed-off-by: Ashin Sabu <[email protected]>

* remove changes to generated text

Signed-off-by: Ashin Sabu <[email protected]>

* unit test for rbacvalidatecommand

Signed-off-by: Ashin Sabu <[email protected]>

* codegen changes

Signed-off-by: Ashin Sabu <[email protected]>

* retrigger ci pipeline

Signed-off-by: Ashin Sabu <[email protected]>

* retrigger ci pipeline

Signed-off-by: Ashin Sabu <[email protected]>

* review comments and test changes

Signed-off-by: Ashin Sabu <[email protected]>

* codegen changes

Signed-off-by: Ashin Sabu <[email protected]>

* codegen changes - post rebase

Signed-off-by: Ashin Sabu <[email protected]>

---------

Signed-off-by: Ashin Sabu <[email protected]>
Signed-off-by: Kevin Lyda <[email protected]>
  • Loading branch information
ashinsabu3 authored and lyda committed Mar 28, 2024
1 parent 9e61df2 commit 62c0ada
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 34 deletions.
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.
`,
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

0 comments on commit 62c0ada

Please sign in to comment.