Skip to content

Commit fe4ebdf

Browse files
authored
Merge pull request #240 from nginx/areste-capture-entitlement-data
Collect JWT payload data
2 parents 15c3932 + e4898af commit fe4ebdf

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

pkg/jobs/nic_job_list.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ package jobs
2121
import (
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("\tCould 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+
5776
func 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("\tCould 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("\tCould 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("\tCould 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("\tConfigMap %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("\tCould 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("\tSecret %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("\tCould 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("\tCould 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

Comments
 (0)