1
1
package storageclient
2
2
3
3
import (
4
- "context"
4
+ gcontext "context"
5
5
"fmt"
6
6
"os"
7
+ "sync"
8
+ "time"
7
9
8
10
apimachineryerrors "k8s.io/apimachinery/pkg/api/errors"
9
11
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12
+ "k8s.io/apimachinery/pkg/watch"
10
13
"k8s.io/client-go/rest"
11
14
"k8s.io/client-go/tools/clientcmd"
12
15
16
+ "sniffer/pkg/context"
17
+
18
+ "github.com/kubescape/go-logger"
19
+ "github.com/kubescape/go-logger/helpers"
13
20
spdxv1beta1 "github.com/kubescape/storage/pkg/apis/softwarecomposition/v1beta1"
14
21
spdxclient "github.com/kubescape/storage/pkg/generated/clientset/versioned"
15
22
)
16
23
17
24
const (
18
- KubeConfig = "KUBECONFIG"
19
- KubescapeNamespace = "kubescape"
25
+ KubeConfig = "KUBECONFIG"
26
+ KubescapeNamespace = "kubescape"
27
+ SBOMServerStateExist SBOMServerState = "Exist"
28
+ SBOMServerStateDeleted SBOMServerState = "Deleted"
29
+ retryWatcherSleep = 30
20
30
)
21
31
32
+ type SBOMServerState string
33
+
34
+ type SBOMMetadata struct {
35
+ SBOMID string
36
+ SBOMServerState
37
+ }
38
+
22
39
type StorageK8SAggregatedAPIClient struct {
23
- clientset * spdxclient.Clientset
40
+ clientset * spdxclient.Clientset
41
+ readySBOMs sync.Map
24
42
}
25
43
26
44
var storageclientErrors map [string ]error
@@ -45,13 +63,75 @@ func CreateSBOMStorageK8SAggregatedAPIClient() (*StorageK8SAggregatedAPIClient,
45
63
if err != nil {
46
64
return nil , fmt .Errorf ("failed to create K8S Aggregated API Client with err: %v" , err )
47
65
}
48
- return & StorageK8SAggregatedAPIClient {
49
- clientset : clientset ,
50
- }, nil
66
+ storageClient := & StorageK8SAggregatedAPIClient {
67
+ clientset : clientset ,
68
+ readySBOMs : sync.Map {},
69
+ }
70
+
71
+ go storageClient .watchForSBOMs ()
72
+
73
+ return storageClient , nil
74
+ }
75
+
76
+ func (sc * StorageK8SAggregatedAPIClient ) watchForSBOMs () {
77
+ for {
78
+ watcher , err := sc .clientset .SpdxV1beta1 ().SBOMSPDXv2p3s (KubescapeNamespace ).Watch (gcontext .TODO (), metav1.ListOptions {})
79
+ if err != nil {
80
+ logger .L ().Ctx (context .GetBackgroundContext ()).Error ("Watch for SBOMs failed " , helpers .Error (err ))
81
+ logger .L ().Ctx (context .GetBackgroundContext ()).Error ("Retry in " , helpers .String (fmt .Sprintf ("%d" , retryWatcherSleep ), " seconds" ))
82
+ time .Sleep (retryWatcherSleep * time .Second )
83
+ continue
84
+ }
85
+ for {
86
+ event , chanActive := <- watcher .ResultChan ()
87
+ if ! chanActive {
88
+ watcher .Stop ()
89
+ break
90
+ }
91
+ if event .Type == watch .Error {
92
+ watcher .Stop ()
93
+ break
94
+ }
95
+
96
+ SBOM , ok := event .Object .(* spdxv1beta1.SBOMSPDXv2p3 )
97
+ if ! ok {
98
+ continue
99
+ }
100
+
101
+ switch event .Type {
102
+ case watch .Added :
103
+ SBOMmetadataAdded := SBOMMetadata {
104
+ SBOMID : SBOM .Name ,
105
+ SBOMServerState : SBOMServerStateExist ,
106
+ }
107
+ sc .readySBOMs .Store (SBOM .Name , SBOMmetadataAdded )
108
+ logger .L ().Debug (fmt .Sprintf ("new SBOM %s was detected in storage with labels: %v" , SBOM .Name , SBOM .Labels ))
109
+ case watch .Deleted :
110
+ SBOMmetadataDeleted := SBOMMetadata {
111
+ SBOMID : SBOM .Name ,
112
+ SBOMServerState : SBOMServerStateDeleted ,
113
+ }
114
+ sc .readySBOMs .Store (SBOM .Name , SBOMmetadataDeleted )
115
+ logger .L ().Debug (fmt .Sprintf ("new SBOM %s was deleted from storage with labels: %v" , SBOM .Name , SBOM .Labels ))
116
+ }
117
+ }
118
+
119
+ }
51
120
}
52
121
53
122
func (sc * StorageK8SAggregatedAPIClient ) GetData (key string ) (any , error ) {
54
- SBOM , err := sc .clientset .SpdxV1beta1 ().SBOMSPDXv2p3s (KubescapeNamespace ).Get (context .TODO (), key , metav1.GetOptions {})
123
+ value , exist := sc .readySBOMs .Load (key )
124
+ if ! exist {
125
+ return nil , fmt .Errorf ("SBOM not exist in server" )
126
+ }
127
+ metadata , ok := value .(SBOMMetadata )
128
+ if ! ok {
129
+ return nil , fmt .Errorf ("failed to convert to SBOM metadata" )
130
+ }
131
+ if metadata .SBOMServerState == SBOMServerStateDeleted {
132
+ return nil , fmt .Errorf ("SBOM not exist in server, SBOM deleted" )
133
+ }
134
+ SBOM , err := sc .clientset .SpdxV1beta1 ().SBOMSPDXv2p3s (KubescapeNamespace ).Get (gcontext .TODO (), key , metav1.GetOptions {})
55
135
if err != nil {
56
136
return nil , err
57
137
}
@@ -62,7 +142,7 @@ func (sc *StorageK8SAggregatedAPIClient) PutData(key string, data any) error {
62
142
if ! ok {
63
143
return fmt .Errorf ("failed to update SBOM: SBOM is not in the right form" )
64
144
}
65
- _ , err := sc .clientset .SpdxV1beta1 ().SBOMSPDXv2p3s (KubescapeNamespace ).Update (context .TODO (), SBOM , metav1.UpdateOptions {})
145
+ _ , err := sc .clientset .SpdxV1beta1 ().SBOMSPDXv2p3s (KubescapeNamespace ).Update (gcontext .TODO (), SBOM , metav1.UpdateOptions {})
66
146
if err != nil {
67
147
return err
68
148
}
@@ -73,7 +153,7 @@ func (sc *StorageK8SAggregatedAPIClient) PostData(key string, data any) error {
73
153
if ! ok {
74
154
return fmt .Errorf ("failed to update SBOM: SBOM is not in the right form" )
75
155
}
76
- retSBOM , err := sc .clientset .SpdxV1beta1 ().SBOMSPDXv2p3s (KubescapeNamespace ).Create (context .TODO (), SBOM , metav1.CreateOptions {})
156
+ retSBOM , err := sc .clientset .SpdxV1beta1 ().SBOMSPDXv2p3s (KubescapeNamespace ).Create (gcontext .TODO (), SBOM , metav1.CreateOptions {})
77
157
if err != nil {
78
158
return err
79
159
}
0 commit comments