Skip to content

Commit

Permalink
Merge branch 'master' into feat/add-intra-generator-param-support
Browse files Browse the repository at this point in the history
  • Loading branch information
KojoRising committed Jun 6, 2022
2 parents c4c4654 + 50bf41f commit 598eff0
Show file tree
Hide file tree
Showing 35 changed files with 547 additions and 114 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG BASE_IMAGE=docker.io/library/ubuntu:21.10
ARG BASE_IMAGE=docker.io/library/ubuntu:22.04
####################################################################################################
# Builder image
# Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image
Expand Down Expand Up @@ -127,4 +127,4 @@ RUN ln -s /usr/local/bin/argocd /usr/local/bin/argocd-server && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-applicationset-controller && \
ln -s /usr/local/bin/argocd /usr/local/bin/argocd-k8s-auth

USER 999
USER 999
1 change: 1 addition & 0 deletions USERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ Currently, the following organizations are **officially** using Argo CD:
1. [GMETRI](https://gmetri.com/)
1. [Gojek](https://www.gojek.io/)
1. [Greenpass](https://www.greenpass.com.br/)
1. [Grupo MasMovil](https://grupomasmovil.com/en/)
1. [Handelsbanken](https://www.handelsbanken.se)
1. [Healy](https://www.healyworld.net)
1. [Helio](https://helio.exchange)
Expand Down
30 changes: 16 additions & 14 deletions cmd/argocd/commands/admin/settings_rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ argocd admin settings rbac can someuser create application 'default/app' --defau
log.Fatalf("could not create k8s client: %v", err)
}

userPolicy, newDefaultRole = getPolicy(policyFile, realClientset, namespace)
userPolicy, newDefaultRole, matchMode := getPolicy(policyFile, realClientset, namespace)

// Use built-in policy as augmentation if requested
if useBuiltin {
Expand All @@ -171,7 +171,7 @@ argocd admin settings rbac can someuser create application 'default/app' --defau
defaultRole = newDefaultRole
}

res := checkPolicy(subject, action, resource, subResource, builtinPolicy, userPolicy, defaultRole, strict)
res := checkPolicy(subject, action, resource, subResource, builtinPolicy, userPolicy, defaultRole, matchMode, strict)
if res {
if !quiet {
fmt.Println("Yes")
Expand Down Expand Up @@ -213,7 +213,7 @@ a local file, and in either CSV or K8s ConfigMap format.
c.HelpFunc()(c, args)
log.Fatalf("Please specify policy to validate using --policy-file")
}
userPolicy, _ := getPolicy(policyFile, nil, "")
userPolicy, _, _ := getPolicy(policyFile, nil, "")
if userPolicy != "" {
if err := rbac.ValidatePolicy(userPolicy); err == nil {
fmt.Printf("Policy is valid.\n")
Expand All @@ -232,11 +232,11 @@ a local file, and in either CSV or K8s ConfigMap format.

// Load user policy file if requested or use Kubernetes client to get the
// appropriate ConfigMap from the current context
func getPolicy(policyFile string, kubeClient kubernetes.Interface, namespace string) (userPolicy string, defaultRole string) {
func getPolicy(policyFile string, kubeClient kubernetes.Interface, namespace string) (userPolicy string, defaultRole string, matchMode string) {
var err error
if policyFile != "" {
// load from file
userPolicy, defaultRole, err = getPolicyFromFile(policyFile)
userPolicy, defaultRole, matchMode, err = getPolicyFromFile(policyFile)
if err != nil {
log.Fatalf("could not read policy file: %v", err)
}
Expand All @@ -245,23 +245,24 @@ func getPolicy(policyFile string, kubeClient kubernetes.Interface, namespace str
if err != nil {
log.Fatalf("could not get configmap: %v", err)
}
userPolicy, defaultRole = getPolicyFromConfigMap(cm)
userPolicy, defaultRole, matchMode = getPolicyFromConfigMap(cm)
}

return userPolicy, defaultRole
return userPolicy, defaultRole, matchMode
}

// getPolicyFromFile loads a RBAC policy from given path
func getPolicyFromFile(policyFile string) (string, string, error) {
func getPolicyFromFile(policyFile string) (string, string, string, error) {
var (
userPolicy string
defaultRole string
matchMode string
)

upol, err := ioutil.ReadFile(policyFile)
if err != nil {
log.Fatalf("error opening policy file: %v", err)
return "", "", err
return "", "", "", err
}

// Try to unmarshal the input file as ConfigMap first. If it succeeds, we
Expand All @@ -271,14 +272,14 @@ func getPolicyFromFile(policyFile string) (string, string, error) {
if err != nil {
userPolicy = string(upol)
} else {
userPolicy, defaultRole = getPolicyFromConfigMap(upolCM)
userPolicy, defaultRole, matchMode = getPolicyFromConfigMap(upolCM)
}

return userPolicy, defaultRole, nil
return userPolicy, defaultRole, matchMode, nil
}

// Retrieve policy information from a ConfigMap
func getPolicyFromConfigMap(cm *corev1.ConfigMap) (string, string) {
func getPolicyFromConfigMap(cm *corev1.ConfigMap) (string, string, string) {
var (
userPolicy string
defaultRole string
Expand All @@ -295,7 +296,7 @@ func getPolicyFromConfigMap(cm *corev1.ConfigMap) (string, string) {
}
}

return userPolicy, defaultRole
return userPolicy, defaultRole, cm.Data[rbac.ConfigMapMatchModeKey]
}

// getPolicyConfigMap fetches the RBAC config map from K8s cluster
Expand All @@ -309,9 +310,10 @@ func getPolicyConfigMap(client kubernetes.Interface, namespace string) (*corev1.

// checkPolicy checks whether given subject is allowed to execute specified
// action against specified resource
func checkPolicy(subject, action, resource, subResource, builtinPolicy, userPolicy, defaultRole string, strict bool) bool {
func checkPolicy(subject, action, resource, subResource, builtinPolicy, userPolicy, defaultRole, matchMode string, strict bool) bool {
enf := rbac.NewEnforcer(nil, "argocd", "argocd-rbac-cm", nil)
enf.SetDefaultRole(defaultRole)
enf.SetMatchMode(matchMode)
if builtinPolicy != "" {
if err := enf.SetBuiltinPolicy(builtinPolicy); err != nil {
log.Fatalf("could not set built-in policy: %v", err)
Expand Down
76 changes: 68 additions & 8 deletions cmd/argocd/commands/admin/settings_rbac_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,17 @@ func Test_isValidRBACResource(t *testing.T) {
}

func Test_PolicyFromCSV(t *testing.T) {
uPol, dRole := getPolicy("testdata/rbac/policy.csv", nil, "")
uPol, dRole, matchMode := getPolicy("testdata/rbac/policy.csv", nil, "")
require.NotEmpty(t, uPol)
require.Empty(t, dRole)
require.Empty(t, matchMode)
}

func Test_PolicyFromYAML(t *testing.T) {
uPol, dRole := getPolicy("testdata/rbac/argocd-rbac-cm.yaml", nil, "")
uPol, dRole, matchMode := getPolicy("testdata/rbac/argocd-rbac-cm.yaml", nil, "")
require.NotEmpty(t, uPol)
require.Equal(t, "role:unknown", dRole)
require.Empty(t, matchMode)
}

func Test_PolicyFromK8s(t *testing.T) {
Expand All @@ -64,28 +66,86 @@ func Test_PolicyFromK8s(t *testing.T) {
"policy.default": "role:unknown",
},
})
uPol, dRole := getPolicy("", kubeclientset, "argocd")
uPol, dRole, matchMode := getPolicy("", kubeclientset, "argocd")
require.NotEmpty(t, uPol)
require.Equal(t, "role:unknown", dRole)
require.Equal(t, "", matchMode)

t.Run("get applications", func(t *testing.T) {
ok := checkPolicy("role:user", "get", "applications", "*/*", assets.BuiltinPolicyCSV, uPol, dRole, true)
ok := checkPolicy("role:user", "get", "applications", "*/*", assets.BuiltinPolicyCSV, uPol, dRole, "", true)
require.True(t, ok)
})
t.Run("get clusters", func(t *testing.T) {
ok := checkPolicy("role:user", "get", "clusters", "*", assets.BuiltinPolicyCSV, uPol, dRole, true)
ok := checkPolicy("role:user", "get", "clusters", "*", assets.BuiltinPolicyCSV, uPol, dRole, "", true)
require.True(t, ok)
})
t.Run("get certificates", func(t *testing.T) {
ok := checkPolicy("role:user", "get", "certificates", "*", assets.BuiltinPolicyCSV, uPol, dRole, true)
ok := checkPolicy("role:user", "get", "certificates", "*", assets.BuiltinPolicyCSV, uPol, dRole, "", true)
require.False(t, ok)
})
t.Run("get certificates by default role", func(t *testing.T) {
ok := checkPolicy("role:user", "get", "certificates", "*", assets.BuiltinPolicyCSV, uPol, "role:readonly", true)
ok := checkPolicy("role:user", "get", "certificates", "*", assets.BuiltinPolicyCSV, uPol, "role:readonly", "glob", true)
require.True(t, ok)
})
t.Run("get certificates by default role without builtin policy", func(t *testing.T) {
ok := checkPolicy("role:user", "get", "certificates", "*", "", uPol, "role:readonly", true)
ok := checkPolicy("role:user", "get", "certificates", "*", "", uPol, "role:readonly", "glob", true)
require.False(t, ok)
})
t.Run("use regex match mode instead of glob", func(t *testing.T) {
ok := checkPolicy("role:user", "get", "certificates", ".*", assets.BuiltinPolicyCSV, uPol, "role:readonly", "regex", true)
require.False(t, ok)
})
}

func Test_PolicyFromK8sUsingRegex(t *testing.T) {
policy := `
p, role:user, clusters, get, .+, allow
p, role:user, clusters, get, https://kubernetes.*, deny
p, role:user, applications, get, .*, allow
p, role:user, applications, create, .*/.*, allow`

kubeclientset := fake.NewSimpleClientset(&v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "argocd-rbac-cm",
Namespace: "argocd",
},
Data: map[string]string{
"policy.csv": policy,
"policy.default": "role:unknown",
"policy.matchMode": "regex",
},
})
uPol, dRole, matchMode := getPolicy("", kubeclientset, "argocd")
require.NotEmpty(t, uPol)
require.Equal(t, "role:unknown", dRole)
require.Equal(t, "regex", matchMode)

builtInPolicy := `
p, role:readonly, certificates, get, .*, allow
p, role:, certificates, get, .*, allow`

t.Run("get applications", func(t *testing.T) {
ok := checkPolicy("role:user", "get", "applications", ".*/.*", builtInPolicy, uPol, dRole, "regex", true)
require.True(t, ok)
})
t.Run("get clusters", func(t *testing.T) {
ok := checkPolicy("role:user", "get", "clusters", ".*", builtInPolicy, uPol, dRole, "regex", true)
require.True(t, ok)
})
t.Run("get certificates", func(t *testing.T) {
ok := checkPolicy("role:user", "get", "certificates", ".*", builtInPolicy, uPol, dRole, "regex", true)
require.False(t, ok)
})
t.Run("get certificates by default role", func(t *testing.T) {
ok := checkPolicy("role:user", "get", "certificates", ".*", builtInPolicy, uPol, "role:readonly", "regex", true)
require.True(t, ok)
})
t.Run("get certificates by default role without builtin policy", func(t *testing.T) {
ok := checkPolicy("role:user", "get", "certificates", ".*", "", uPol, "role:readonly", "regex", true)
require.False(t, ok)
})
t.Run("use glob match mode instead of regex", func(t *testing.T) {
ok := checkPolicy("role:user", "get", "certificates", ".+", builtInPolicy, uPol, dRole, "glob", true)
require.False(t, ok)
})
}
24 changes: 23 additions & 1 deletion docs/operator-manual/rbac.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,29 @@ Breaking down the permissions definition differs slightly between applications a

Resources: `clusters`, `projects`, `applications`, `repositories`, `certificates`, `accounts`, `gpgkeys`, `logs`, `exec`

Actions: `get`, `create`, `update`, `delete`, `sync`, `override`, `action`
Actions: `get`, `create`, `update`, `delete`, `sync`, `override`,
`action/<group/kind/action-name>`

#### Application resources

The resource path for application objects is of the form
`<project-name>/<application-name>`.

Delete access to sub-resources of a project, such as a rollout or a pod, cannot
be managed granularly. `<project-name>/<application-name>` grants access to all
subresources of an application.

#### The `action` action

The `action` action corresponds to either built-in resource customizations defined
[in the Argo CD repository](https://github.com/argoproj/argo-cd/search?q=filename%3Aaction.lua+path%3Aresource_customizations),
or to [custom resource actions](resource_actions.md#custom-resource-actions) defined by you.
The `action` path is of the form `action/<api-group>/<Kind>/<action-name>`. For
example, a resource customization path
`resource_customizations/extensions/DaemonSet/actions/restart/action.lua`
corresponds to the `action` path `action/extensions/DaemonSet/restart`. You can
also use glob patterns in the action path: `action/*` (or regex patterns if you have
[enabled the `regex` match mode](https://github.com/argoproj/argo-cd/blob/master/docs/operator-manual/argocd-rbac-cm.yaml)).

#### `exec` resource

Expand Down
60 changes: 49 additions & 11 deletions docs/operator-manual/upgrading/2.3-2.4.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@

## KSonnet support is removed

The [https://ksonnet.io/] had been deprecated in [2019](https://github.com/ksonnet/ksonnet/pull/914/files) and no longer maintained.
The time has come to remove it from the ArgoCD.
Ksonnet was deprecated in [2019](https://github.com/ksonnet/ksonnet/pull/914/files) and is no longer maintained.
The time has come to remove it from the Argo CD.

## Helm 2 support is removed

Helm 2 is not been officially supported since [Nov 2020](https://helm.sh/blog/helm-2-becomes-unsupported/). In order to ensure a smooth transition
Helm 2 support was preserved in the Argo CD. We feel that Helm 3 is stable and it is time to drop Helm 2 support.

Helm 2 has not been officially supported since [Nov 2020](https://helm.sh/blog/helm-2-becomes-unsupported/). In order to ensure a smooth transition,
Helm 2 support was preserved in the Argo CD. We feel that Helm 3 is stable, and it is time to drop Helm 2 support.

## Configure RBAC to account for new `exec` resource

Expand Down Expand Up @@ -77,11 +76,20 @@ p, role:test-db-admins, applications, *, staging-db-admins/*, allow
p, role:test-db-admins, logs, get, staging-db-admins/*, allow
```

### Known UI issue
## Known UI issue

Currently, upon pressing the "LOGS" tab in pod view by users who don't have an explicit allow get logs policy, the red "unable to load data: Internal error" is received in the bottom of the screen, and "Failed to load data, please try again" is displayed.

## Remove the shared volume from any sidecar plugins
## Test repo-server with its new dedicated Service Account

As a security enhancement, the argocd-repo-server Deployment uses its own Service Account instead of `default`.

If you have a custom environment that might depend on repo-server using the `default` Service Account (such as a plugin
that uses the Service Account for auth), be sure to test before deploying the 2.4 upgrade to production.

## Plugins

### Remove the shared volume from any sidecar plugins

As a security enhancement, [sidecar plugins](../../user-guide/config-management-plugins.md#option-2-configure-plugin-via-sidecar)
no longer share the /tmp directory with the repo-server.
Expand All @@ -108,9 +116,39 @@ spec:
emptyDir: {}
```

## Test repo-server with its new dedicated Service Account
### Update plugins to use newly-prefixed environment variables

As a security enhancement, the argocd-repo-server Deployment uses its own Service Account instead of `default`.
If you use plugins that depend on user-supplied environment variables, then they must be updated to be compatible with
Argo CD 2.4. Here is an example of user-supplied environment variables in the `plugin` section of an Application spec:

If you have a custom environment that might depend on repo-server using the `default` Service Account (such as a plugin
that uses the Service Account for auth), be sure to test before deploying the 2.4 upgrade to production.
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
source:
plugin:
env:
- name: FOO
value: bar
```

Going forward, all user-supplied environment variables will be prefixed with `ARGOCD_ENV_` before being sent to the
plugin's `init`, `generate`, or `discover` commands. This prevents users from setting potentially-sensitive environment
variables.

If you have written a custom plugin which handles user-provided environment variables, update it to handle the new
prefix.

If you use a third-party plugin which does not explicitly advertise Argo CD 2.4 support, it might not handle the
prefixed environment variables. Open an issue with the plugin's authors and confirm support before upgrading to Argo CD
2.4.

### Confirm sidecar plugins have all necessary environment variables

A bug in < 2.4 caused `init` and `generate` commands to receive environment variables from the main repo-server
container, taking precedence over environment variables from the plugin's sidecar.

Starting in 2.4, sidecar plugins will not receive environment variables from the main repo-server container. Make sure
that any environment variables necessary for the sidecar plugin to function are set on the sidecar plugin.

argocd-cm plugins will continue to receive environment variables from the main repo-server container.
6 changes: 3 additions & 3 deletions docs/operator-manual/user-management/google.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ If you've never configured this, you'll be redirected straight to this if you tr

### Configure Argo to use OpenID Connect

Edit `argo-cm` and add the following `dex.config` to the data section, replacing `clientID` and `clientSecret` with the values you saved before:
Edit `argocd-cm` and add the following `dex.config` to the data section, replacing `clientID` and `clientSecret` with the values you saved before:

```yaml
data:
Expand Down Expand Up @@ -113,7 +113,7 @@ data:

### Configure Argo to use the new Google SAML App

Edit `argo-cm` and add the following `dex.config` to the data section, replacing the `caData`, `argocd.example.com`, `sso-url`, and optionally `google-entity-id` with your values from the Google SAML App:
Edit `argocd-cm` and add the following `dex.config` to the data section, replacing the `caData`, `argocd.example.com`, `sso-url`, and optionally `google-entity-id` with your values from the Google SAML App:

```yaml
data:
Expand Down Expand Up @@ -211,7 +211,7 @@ Go through the same steps as in [OpenID Connect using Dex](#openid-connect-using
defaultMode: 420
secretName: argocd-google-groups-json

3. Edit `argo-cm` and add the following `dex.config` to the data section, replacing `clientID` and `clientSecret` with the values you saved before, `adminEmail` with the address for the admin user you're going to impersonate, and editing `redirectURI` with your Argo CD domain:
3. Edit `argocd-cm` and add the following `dex.config` to the data section, replacing `clientID` and `clientSecret` with the values you saved before, `adminEmail` with the address for the admin user you're going to impersonate, and editing `redirectURI` with your Argo CD domain:

dex.config: |
connectors:
Expand Down
Loading

0 comments on commit 598eff0

Please sign in to comment.