Skip to content
This repository was archived by the owner on Jan 16, 2023. It is now read-only.

Commit d5f9ae0

Browse files
committed
DEV-52508 Argus deployment rbac privilege compatibility improvement
1 parent 87941be commit d5f9ae0

File tree

12 files changed

+139
-42
lines changed

12 files changed

+139
-42
lines changed

cmd/watch.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@ import (
77
"os"
88
"time"
99

10-
"github.com/logicmonitor/k8s-argus/pkg"
10+
"github.com/logicmonitor/k8s-argus/pkg/rbac"
11+
12+
argus "github.com/logicmonitor/k8s-argus/pkg"
1113
"github.com/logicmonitor/k8s-argus/pkg/config"
1214
"github.com/logicmonitor/k8s-argus/pkg/constants"
1315
"github.com/logicmonitor/k8s-argus/pkg/healthz"
1416
"github.com/logicmonitor/k8s-collectorset-controller/api"
1517
collectorsetconstants "github.com/logicmonitor/k8s-collectorset-controller/pkg/constants"
1618
log "github.com/sirupsen/logrus"
1719
"github.com/spf13/cobra"
18-
grpc "google.golang.org/grpc"
20+
"google.golang.org/grpc"
1921
"google.golang.org/grpc/connectivity"
2022
healthpb "google.golang.org/grpc/health/grpc_health_v1"
2123
)
@@ -48,6 +50,9 @@ var watchCmd = &cobra.Command{
4850
log.Fatal(err.Error())
4951
}
5052

53+
// Init the rbac component
54+
rbac.Init(base.K8sClient)
55+
5156
// Set up a gRPC connection to the collectorset controller.
5257
conn, err := grpc.Dial(config.Address, grpc.WithInsecure())
5358
if err != nil {

pkg/argus.go

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package argus
33
import (
44
"time"
55

6-
"github.com/logicmonitor/k8s-argus/pkg/utilities"
7-
86
"github.com/logicmonitor/k8s-argus/pkg/watch/deployment"
97

108
"github.com/logicmonitor/k8s-argus/pkg/config"
@@ -23,7 +21,6 @@ import (
2321
"github.com/logicmonitor/lm-sdk-go/client"
2422
log "github.com/sirupsen/logrus"
2523
v1 "k8s.io/api/core/v1"
26-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2724
"k8s.io/apimachinery/pkg/fields"
2825
"k8s.io/client-go/kubernetes"
2926
"k8s.io/client-go/rest"
@@ -79,14 +76,11 @@ func NewArgus(base *types.Base, client api.CollectorSetControllerClient) (*Argus
7976
Base: base,
8077
}
8178

82-
hasDeploymentRbac := checkHasDeploymentRbac(base)
83-
log.Infof("Has deployment rbac: %+v", hasDeploymentRbac)
84-
8579
// init sync to delete the non-exist resource devices through logicmonitor API
8680
initSyncer := sync.InitSyncer{
8781
DeviceManager: deviceManager,
8882
}
89-
initSyncer.InitSync(hasDeploymentRbac)
83+
initSyncer.InitSync()
9084

9185
deviceGroups, err := deviceTree.CreateDeviceTree()
9286
if err != nil {
@@ -119,34 +113,14 @@ func NewArgus(base *types.Base, client api.CollectorSetControllerClient) (*Argus
119113
&pod.Watcher{
120114
DeviceManager: deviceManager,
121115
},
122-
}
123-
124-
if hasDeploymentRbac {
125-
argus.Watchers = append(argus.Watchers, &deployment.Watcher{
116+
&deployment.Watcher{
126117
DeviceManager: deviceManager,
127-
})
118+
},
128119
}
129120

130121
return argus, nil
131122
}
132123

133-
func checkHasDeploymentRbac(base *types.Base) bool {
134-
clusterRole, err := base.K8sClient.RbacV1beta1().ClusterRoles().Get("argus", metav1.GetOptions{})
135-
if err != nil {
136-
log.Errorf("Get clusterRoles failed: %+v", err)
137-
} else {
138-
for _, rule := range clusterRole.Rules {
139-
if len(rule.APIGroups) == 0 {
140-
continue
141-
}
142-
if utilities.Contains("apps", rule.APIGroups) && utilities.Contains("deployments", rule.Resources) {
143-
return true
144-
}
145-
}
146-
}
147-
return false
148-
}
149-
150124
// NewBase instantiates and returns the base structure used throughout Argus.
151125
func NewBase(config *config.Config) (*types.Base, error) {
152126
// LogicMonitor API client.
@@ -173,6 +147,10 @@ func NewBase(config *config.Config) (*types.Base, error) {
173147
// Watch watches the API for events.
174148
func (a *Argus) Watch() {
175149
for _, w := range a.Watchers {
150+
if !w.CheckRBAC() {
151+
log.Warnf("Resource %s has no rbac, ignore watch", w.Resource())
152+
continue
153+
}
176154
watchlist := cache.NewListWatchFromClient(getK8sRESTClient(a.K8sClient, w.APIVersion()), w.Resource(), v1.NamespaceAll, fields.Everything())
177155
_, controller := cache.NewInformer(
178156
watchlist,

pkg/device/device.go

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,21 @@ func buildDevice(c *config.Config, client api.CollectorSetControllerClient, opti
5353
return device
5454
}
5555

56+
func (m *Manager) addDevice(device *models.Device) (*lm.AddDeviceOK, error) {
57+
params := lm.NewAddDeviceParams()
58+
addFromWizard := false
59+
params.SetAddFromWizard(&addFromWizard)
60+
params.SetBody(device)
61+
restResponse, err := m.LMClient.LM.AddDevice(params)
62+
if err != nil {
63+
_, ok := err.(*lm.AddDeviceDefault)
64+
if !ok {
65+
return nil, err
66+
}
67+
}
68+
return restResponse, nil
69+
}
70+
5671
// checkAndUpdateExistingDevice tries to find and update the devices which needs to be changed
5772
func (m *Manager) checkAndUpdateExistingDevice(device *models.Device) (*models.Device, error) {
5873
oldDevice, err := m.FindByDisplayName(*device.DisplayName)
@@ -64,21 +79,22 @@ func (m *Manager) checkAndUpdateExistingDevice(device *models.Device) (*models.D
6479
}
6580

6681
// the device which is not changed will be ignored
67-
if *device.Name == *oldDevice.Name {
82+
if *device.Name == *oldDevice.Name && oldDevice.PreferredCollectorID == device.PreferredCollectorID {
6883
log.Infof("No changes to device (%s). Ignoring update", *device.DisplayName)
6984
return device, nil
7085
}
7186

7287
// the device of the other cluster will be ignored
73-
oldClusterName := ""
74-
if oldDevice.CustomProperties != nil && len(oldDevice.CustomProperties) > 0 {
75-
for _, cp := range oldDevice.CustomProperties {
76-
if *cp.Name == constants.K8sClusterNamePropertyKey {
77-
oldClusterName = *cp.Value
78-
}
79-
}
80-
}
88+
oldClusterName := getPropertyValue(oldDevice, constants.K8sClusterNamePropertyKey)
89+
8190
if oldClusterName != m.Config().ClusterName {
91+
newDisplayName := fmt.Sprintf("%s-%s", *device.DisplayName, m.Config().ClusterName)
92+
device.DisplayName = &newDisplayName
93+
_, err := m.addDevice(device)
94+
if err != nil {
95+
return device, err
96+
}
97+
8298
log.Infof("Device (%s) belongs to a different cluster (%s). Ignoring update", *device.DisplayName, oldClusterName)
8399
return device, nil
84100
}
@@ -91,6 +107,27 @@ func (m *Manager) checkAndUpdateExistingDevice(device *models.Device) (*models.D
91107
return newDevice, nil
92108
}
93109

110+
func getPropertyValue(device *models.Device, propertyName string) string {
111+
if device == nil {
112+
return ""
113+
}
114+
if len(device.CustomProperties) > 0 {
115+
for _, cp := range device.CustomProperties {
116+
if *cp.Name == propertyName {
117+
return *cp.Value
118+
}
119+
}
120+
}
121+
if len(device.SystemProperties) > 0 {
122+
for _, cp := range device.SystemProperties {
123+
if *cp.Name == propertyName {
124+
return *cp.Value
125+
}
126+
}
127+
}
128+
return ""
129+
}
130+
94131
func (m *Manager) updateAndReplace(id int32, device *models.Device) (*models.Device, error) {
95132
opType := "replace"
96133
params := lm.NewUpdateDeviceParams()

pkg/rbac/rbac.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package rbac
2+
3+
import (
4+
log "github.com/sirupsen/logrus"
5+
v1 "k8s.io/api/core/v1"
6+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
7+
"k8s.io/client-go/kubernetes"
8+
)
9+
10+
const (
11+
rbacFlagDefault = 0
12+
rbacFlagEnable = 1
13+
rbacFlagDisabled = -1
14+
)
15+
16+
var (
17+
client *kubernetes.Clientset
18+
19+
deploymentRBACFlag = 0
20+
)
21+
22+
func Init(k8sclient *kubernetes.Clientset) {
23+
client = k8sclient
24+
}
25+
26+
// HasDeploymentRBAC is a function that check if the deployment resource has rbac permissions
27+
func HasDeploymentRBAC() bool {
28+
if deploymentRBACFlag != rbacFlagDefault {
29+
return deploymentRBACFlag == rbacFlagEnable
30+
}
31+
_, err := client.AppsV1beta2().Deployments(v1.NamespaceAll).List(metav1.ListOptions{})
32+
if err != nil {
33+
deploymentRBACFlag = rbacFlagDisabled
34+
log.Error("List deployments failed: %+v", err)
35+
} else {
36+
deploymentRBACFlag = rbacFlagEnable
37+
}
38+
39+
return deploymentRBACFlag == rbacFlagEnable
40+
41+
}

pkg/sync/initsyncer.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package sync
33
import (
44
"sync"
55

6+
"github.com/logicmonitor/k8s-argus/pkg/rbac"
7+
68
"github.com/logicmonitor/k8s-argus/pkg/constants"
79
"github.com/logicmonitor/k8s-argus/pkg/device"
810
"github.com/logicmonitor/k8s-argus/pkg/devicegroup"
@@ -20,7 +22,7 @@ type InitSyncer struct {
2022
}
2123

2224
// InitSync implements the initial sync through logicmonitor API
23-
func (i *InitSyncer) InitSync(hasDeploymentRbac bool) {
25+
func (i *InitSyncer) InitSync() {
2426
log.Infof("Start to sync the resource devices")
2527
rest := i.getDeviceGroups()
2628
if rest == nil {
@@ -54,7 +56,8 @@ func (i *InitSyncer) InitSync(hasDeploymentRbac bool) {
5456
case constants.DeploymentDeviceGroupName:
5557
go func() {
5658
defer wg.Done()
57-
if !hasDeploymentRbac {
59+
if !rbac.HasDeploymentRBAC() {
60+
log.Warnf("Resource deployments has no rbac, ignore sync")
5861
return
5962
}
6063
i.initSyncPodsOrServicesOrDeploys(constants.DeploymentDeviceGroupName, rest.ID)

pkg/tree/tree.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package tree
33
import (
44
"github.com/logicmonitor/k8s-argus/pkg/constants"
55
"github.com/logicmonitor/k8s-argus/pkg/devicegroup"
6+
"github.com/logicmonitor/k8s-argus/pkg/rbac"
67
"github.com/logicmonitor/k8s-argus/pkg/types"
78
)
89

@@ -87,6 +88,10 @@ func (d *DeviceTree) CreateDeviceTree() (map[string]int32, error) {
8788
case constants.ClusterDeviceGroupPrefix + d.Config.ClusterName:
8889
// don't do anything for the root cluster group
8990
default:
91+
if opts.Name == constants.DeploymentDeviceGroupName && !rbac.HasDeploymentRBAC() {
92+
// deployment has no rbac, don't create the group
93+
continue
94+
}
9095
opts.ParentID = deviceGroups[constants.ClusterDeviceGroupPrefix+d.Config.ClusterName]
9196
}
9297

pkg/types/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type Base struct {
1818
// Watcher is the LogicMonitor Watcher interface.
1919
type Watcher interface {
2020
APIVersion() string
21+
CheckRBAC() bool
2122
Resource() string
2223
ObjType() runtime.Object
2324
AddFunc() func(obj interface{})

pkg/watch/deployment/deployment.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"fmt"
77
"strconv"
88

9+
"github.com/logicmonitor/k8s-argus/pkg/rbac"
10+
911
"github.com/logicmonitor/k8s-argus/pkg/constants"
1012
"github.com/logicmonitor/k8s-argus/pkg/types"
1113
"github.com/logicmonitor/k8s-argus/pkg/utilities"
@@ -30,6 +32,11 @@ func (w *Watcher) APIVersion() string {
3032
return constants.K8sAPIVersionAppsV1beta2
3133
}
3234

35+
// CheckRBAC is a function that check the resource has RBAC permissions.
36+
func (w *Watcher) CheckRBAC() bool {
37+
return rbac.HasDeploymentRBAC()
38+
}
39+
3340
// Resource is a function that implements the Watcher interface.
3441
func (w *Watcher) Resource() string {
3542
return resource

pkg/watch/namespace/namespace.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ func (w *Watcher) APIVersion() string {
2525
return constants.K8sAPIVersionV1
2626
}
2727

28+
// CheckRBAC is a function that check the resource has RBAC permissions.
29+
func (w *Watcher) CheckRBAC() bool {
30+
return true
31+
}
32+
2833
// Resource is a function that implements the Watcher interface.
2934
func (w *Watcher) Resource() string {
3035
return resource

pkg/watch/node/node.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ func (w *Watcher) APIVersion() string {
3434
return constants.K8sAPIVersionV1
3535
}
3636

37+
// CheckRBAC is a function that check the resource has RBAC permissions.
38+
func (w *Watcher) CheckRBAC() bool {
39+
return true
40+
}
41+
3742
// Resource is a function that implements the Watcher interface.
3843
func (w *Watcher) Resource() string {
3944
return resource

0 commit comments

Comments
 (0)