teleport/lib/utils/copy.go
Sasha Klizhentas c623aa4dc5 Add cluster labels
Fixes #3604

This commit adds support for cluster_labels
role parameter limiting access to remote clusters by label.
New tctl update rc provides interface to set labels on remote clusters.

Consider two clusers, `one` - root and `remote` - leaf.

```bash
$ tsh clusters
Cluster Name Status
------------ ------
one          online
two          online
```

Create the trusted cluster join token with labels:

```bash
$ tctl tokens add --type=trusted_cluster --labels=env=prod
```

Every cluster joined using this token will inherit env:prod labels.

Alternatively, update remote cluster labels by modifying
`rc` command. Letting remote clusters to propagate their labels
creates a problem of rogue clusters updating their labels to bad values.

Instead, administrator of root cluster control the labels
using remote clusters API without fear of override:

```bash
$ tctl get rc

kind: remote_cluster
metadata:
  name: two
status:
  connection: online
  last_heartbeat: "2020-09-14T03:13:59.35518164Z"
version: v3
```

```bash
$ tctl update rc/two --set-labels=env=prod

cluster two has been updated
```

```bash
$ tctl get rc
kind: remote_cluster
metadata:
  labels:
    env: prod
  name: two
status:
  connection: online
  last_heartbeat: "2020-09-14T03:13:59.35518164Z"
```

Update the role to deny access to prod env:

```yaml
kind: role
metadata:
  name: dev
spec:
  allow:
    logins: [root]
    node_labels:
      '*': '*'

    # Cluster labels control what clusters user can connect to. The wildcard ('*') means
    # any cluster. If no role in the role set is using labels and cluster is not labeled,
    # the cluster labels check is not applied. Otherwise, cluster labels are always enforced.
    # This makes the feature backwards-compatible.
    cluster_labels:
      'env': 'staging'
  deny:
    # cluster labels control what clusters user can connect to. The wildcard ('*') means
    # any cluster. By default none is set in deny rules to preserve backwards compatibility
    cluster_labels:
      'env': 'prod'
```

```bash
$ tctl create -f dev.yaml
```

Cluster two is now invisible to user with `dev` role.

```bash
$ tsh clusters
Cluster Name Status
------------ ------
one          online
```
2020-11-03 16:10:15 -08:00

80 lines
1.7 KiB
Go

/*
Copyright 2017 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package utils
// CopyStringsMap returns a copy of the strings map
func CopyStringsMap(in map[string]string) map[string]string {
if in == nil {
return nil
}
out := make(map[string]string, len(in))
for key, val := range in {
out[key] = val
}
return out
}
// CopyByteSlice returns a copy of the byte slice.
func CopyByteSlice(in []byte) []byte {
if in == nil {
return nil
}
out := make([]byte, len(in))
copy(out, in)
return out
}
// CopyByteSlices returns a copy of the byte slices.
func CopyByteSlices(in [][]byte) [][]byte {
if in == nil {
return nil
}
out := make([][]byte, len(in))
for i := range in {
out[i] = CopyByteSlice(in[i])
}
return out
}
// CopyStrings makes a deep copy of the passed in string slice and returns
// the copy.
func CopyStrings(in []string) []string {
if in == nil {
return nil
}
out := make([]string, len(in))
copy(out, in)
return out
}
// ReplaceInSlice replaces element old with new and returns a new slice.
func ReplaceInSlice(s []string, old string, new string) []string {
out := make([]string, 0, len(s))
for _, x := range s {
if x == old {
out = append(out, new)
} else {
out = append(out, x)
}
}
return out
}