@@ -21,6 +21,7 @@ package jobs
2121import (
2222 "bytes"
2323 "context"
24+ "encoding/base64"
2425 "encoding/json"
2526 "fmt"
2627 "path/filepath"
@@ -30,6 +31,7 @@ import (
3031
3132 "github.com/nginxinc/nginx-k8s-supportpkg/pkg/crds"
3233 "github.com/nginxinc/nginx-k8s-supportpkg/pkg/data_collector"
34+ v1 "k8s.io/api/core/v1"
3335 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3436)
3537
@@ -54,6 +56,23 @@ func ParseNginxIngressProductInfo(res []byte) data_collector.ProductInfo {
5456 return productInfo
5557}
5658
59+ // Returns the first found pod with the 'ingress' substring in its name
60+ func getNginxIngressPod (dc * data_collector.DataCollector , ctx context.Context ) (v1.Pod , error ) {
61+ for _ , namespace := range dc .Namespaces {
62+ pods , err := dc .K8sCoreClientSet .CoreV1 ().Pods (namespace ).List (ctx , metav1.ListOptions {})
63+ if err != nil {
64+ dc .Logger .Printf ("\t Could not retrieve pod list for namespace %s: %v\n " , namespace , err )
65+ } else {
66+ for _ , pod := range pods .Items {
67+ if strings .Contains (pod .Name , "ingress" ) {
68+ return pod , nil
69+ }
70+ }
71+ }
72+ }
73+ return v1.Pod {}, fmt .Errorf ("no nginx-ingress pod found in the provided namespaces" )
74+ }
75+
5776func NICJobList () []Job {
5877 jobList := []Job {
5978 {
@@ -242,6 +261,94 @@ func NICJobList() []Job {
242261 ch <- jobResult
243262 },
244263 },
264+ {
265+ Name : "parse-entitlement" ,
266+ Timeout : time .Second * 10 ,
267+ Execute : func (dc * data_collector.DataCollector , ctx context.Context , ch chan JobResult ) {
268+ jobResult := JobResult {Files : make (map [string ][]byte ), Error : nil }
269+
270+ ingressPod , err := getNginxIngressPod (dc , ctx )
271+ if err != nil {
272+ dc .Logger .Printf ("\t Could not find nginx-ingress pod: %v\n " , err )
273+ jobResult .Error = err
274+ ch <- jobResult
275+ return
276+ }
277+
278+ for _ , container := range ingressPod .Spec .Containers {
279+ if container .Name == "nginx-ingress" {
280+ for _ , arg := range container .Args {
281+ if strings .Contains (arg , "mgmt-configmap" ) {
282+ configMapString := strings .SplitN (arg , "=" , 2 )
283+ if len (configMapString ) != 2 {
284+ dc .Logger .Printf ("\t Could not parse mgmt-configmap argument: %s\n " , arg )
285+ jobResult .Error = fmt .Errorf ("could not parse mgmt-configmap argument: %s" , arg )
286+ ch <- jobResult
287+ return
288+ }
289+ configMapName := strings .Split (configMapString [1 ], "/" )[1 ]
290+ configMapNamespace := strings .Replace (strings .Split (configMapString [1 ], "/" )[0 ], "$(POD_NAMESPACE)" , ingressPod .Namespace , 1 )
291+
292+ configMap , err := dc .K8sCoreClientSet .CoreV1 ().ConfigMaps (configMapNamespace ).Get (ctx , configMapName , metav1.GetOptions {})
293+ if err != nil {
294+ dc .Logger .Printf ("\t Could not retrieve ConfigMap %s in namespace %s: %v\n " , configMapName , configMapNamespace , err )
295+ jobResult .Error = err
296+ ch <- jobResult
297+ return
298+ }
299+
300+ licenseTokenSecretName , exists := configMap .Data ["license-token-secret-name" ]
301+ if ! exists {
302+ dc .Logger .Printf ("\t ConfigMap %s in namespace %s does not contain 'license-token-secret-name' key\n " , configMapName , configMapNamespace )
303+ jobResult .Error = fmt .Errorf ("configmap %s in namespace %s does not contain 'license-token-secret-name' key" , configMapName , configMapNamespace )
304+ ch <- jobResult
305+ return
306+ }
307+
308+ licenseTokenSecret , err := dc .K8sCoreClientSet .CoreV1 ().Secrets (configMapNamespace ).Get (ctx , licenseTokenSecretName , metav1.GetOptions {})
309+ if err != nil {
310+ dc .Logger .Printf ("\t Could not retrieve Secret %s in namespace %s: %v\n " , licenseTokenSecretName , configMapNamespace , err )
311+ jobResult .Error = err
312+ ch <- jobResult
313+ return
314+ }
315+
316+ licenseToken , exists := licenseTokenSecret .Data ["license.jwt" ]
317+ if ! exists {
318+ dc .Logger .Printf ("\t Secret %s in namespace %s does not contain 'license.jwt' key\n " , licenseTokenSecretName , configMapNamespace )
319+ jobResult .Error = fmt .Errorf ("secret %s in namespace %s does not contain 'license.jwt' key" , licenseTokenSecretName , configMapNamespace )
320+ ch <- jobResult
321+ return
322+ }
323+
324+ claim := strings .Split (string (licenseToken ), "." )[1 ]
325+ decodedClaim , err := base64 .RawStdEncoding .DecodeString (claim )
326+ if err != nil {
327+ dc .Logger .Printf ("\t Could not decode license token claim from Secret %s in namespace %s: %v\n " , licenseTokenSecretName , configMapNamespace , err )
328+ jobResult .Error = err
329+ ch <- jobResult
330+ return
331+ }
332+
333+ var prettyJSON bytes.Buffer
334+ err = json .Indent (& prettyJSON , decodedClaim , "" , " " )
335+ if err != nil {
336+ dc .Logger .Printf ("\t Could not format license token claim JSON from Secret %s in namespace %s: %v\n " , licenseTokenSecretName , configMapNamespace , err )
337+ jobResult .Error = err
338+ ch <- jobResult
339+ return
340+ }
341+
342+ fileName := fmt .Sprintf ("%s_payload.json" , licenseTokenSecretName )
343+ jobResult .Files [filepath .Join (dc .BaseDir , "entitlement" , ingressPod .Namespace , fileName )] = prettyJSON .Bytes ()
344+ break
345+ }
346+ }
347+ }
348+ }
349+ ch <- jobResult
350+ },
351+ },
245352 }
246353 return jobList
247354}
0 commit comments