Skip to content

Commit

Permalink
Add container name and hash to vuln slugs (#87)
Browse files Browse the repository at this point in the history
* Add container name and hash to vuln slugs

Signed-off-by: David Wertenteil <dwertent@armosec.io>

* fixed tests

Signed-off-by: David Wertenteil <dwertent@armosec.io>

---------

Signed-off-by: David Wertenteil <dwertent@armosec.io>
  • Loading branch information
dwertent committed Dec 30, 2023
1 parent c947e39 commit e07cb7c
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 9 deletions.
2 changes: 1 addition & 1 deletion instanceidhandler/v1/instanceidhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,5 +133,5 @@ func (id *InstanceID) GetLabels() map[string]string {
}

func (id *InstanceID) GetSlug() (string, error) {
return names.InstanceIDToSlug(id.GetName(), id.GetKind(), id.GetHashed())
return names.InstanceIDToSlug(id.GetName(), id.GetKind(), id.GetContainerName(), id.GetHashed())
}
13 changes: 12 additions & 1 deletion instanceidhandler/v1/instanceidhandler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func TestInstanceIDToDisplayName(t *testing.T) {
name: "reverse-proxy",
containerName: "nginx",
},
want: "pod-reverse-proxy",
want: "pod-reverse-proxy-nginx-2f07-68bd",
wantErr: nil,
},
{
Expand All @@ -176,6 +176,17 @@ func TestInstanceIDToDisplayName(t *testing.T) {
name: "webapp",
containerName: "leader",
},
want: "service-webapp-leader-cca3-8ea7",
wantErr: nil,
},
{
name: "valid instanceID without container name produces matching display name",
input: &InstanceID{
apiVersion: "v1",
namespace: "default",
kind: "Service",
name: "webapp",
},
want: "service-webapp",
wantErr: nil,
},
Expand Down
24 changes: 18 additions & 6 deletions names/slugs.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,21 +136,28 @@ func sanitizeImage(image string) string {
}

// sanitizeInstanceIDSlug returns a sanitized instance ID slug
func sanitizeInstanceIDSlug(instanceIDSlug, hashedID string) string {
func sanitizeInstanceIDSlug(instanceIDSlug, containerName, hashedID string) string {
leadingDigest, trailingDigest := hashedID[:slugHashLength], hashedID[len(hashedID)-slugHashLength:]

// if container name is not empty, add it to the slug, and add the hash as well
// adding the hash is necessary to avoid collisions between different workloads in different namespaces. This is a workaround until we store the vulnerabilitymanifests objects in a separate namespace
if containerName != "" {
instanceIDSlug = fmt.Sprintf("%s-%s", instanceIDSlug, containerName)
instanceIDSlug = fmt.Sprintf("%s-%s-%s", instanceIDSlug, leadingDigest, trailingDigest)
}
if len(instanceIDSlug) < maxHashlessStringLength {
return instanceIDSlug
}
leadingDigest, trailingDigest := hashedID[:slugHashLength], hashedID[len(hashedID)-slugHashLength:]
return fmt.Sprintf("%s-%s-%s", instanceIDSlug[:maxHashlessStringLength], leadingDigest, trailingDigest)

}

// InstanceIDToSlug retuns a human-friendly representation given a description of an instance ID
//
// If the given inputs would produce an invalid slug, it returns an appropriate error
func InstanceIDToSlug(name, kind, hashedID string) (string, error) {
func InstanceIDToSlug(name, kind, containerName, hashedID string) (string, error) {

slug := sanitizeInstanceIDSlug(fmt.Sprintf(instanceIDSlugHashlessFormat, kind, name), hashedID)
slug := sanitizeInstanceIDSlug(fmt.Sprintf(instanceIDSlugHashlessFormat, kind, name), containerName, hashedID)

var err error
slug = strings.ToLower(slug)
Expand Down Expand Up @@ -202,7 +209,7 @@ func StringToSlug(str string) (string, error) {

hashBytes := sha256.Sum256([]byte(str))
hashStr := hex.EncodeToString(hashBytes[:])
slug := sanitizeInstanceIDSlug(sanitizedStr, hashStr)
slug := sanitizeInstanceIDSlug(sanitizedStr, "", hashStr)

slug = strings.ToLower(slug)

Expand All @@ -218,7 +225,7 @@ func resourceToFormattedString(resource workloadinterface.IMetadata) string {
}

// ResourceToSlug returns a human-friendly representation for a given resource
// The slug is generated based on the API version, kind, namespace and name of the resource
// The slug is generated based on the kind and name of the resource
func ResourceToSlug(resource workloadinterface.IMetadata) (string, error) {
return StringToSlug(resourceToFormattedString(resource))
}
Expand All @@ -231,3 +238,8 @@ func RoleBindingResourceToSlug(subject workloadinterface.IMetadata, role workloa
roleBindingName := resourceToFormattedString(roleBinding)
return StringToSlug(fmt.Sprintf("%s-%s-%s", subjectName, roleName, roleBindingName))
}

// Add namespace to slug
func AddNamespaceToSlug(slug, namespace string) string {
return fmt.Sprintf("%s-%s", namespace, slug)
}
23 changes: 22 additions & 1 deletion names/slugs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ func TestInstanceIDToFriendlyName(t *testing.T) {
name string
inputName string
inputNamespace string
inputContainer string
inputKind string
inputHashedID string
want string
Expand All @@ -146,6 +147,26 @@ func TestInstanceIDToFriendlyName(t *testing.T) {
want: "service-webapp",
wantErr: nil,
},
{
name: "valid instanceID with container name produces matching display name",
inputNamespace: "default",
inputContainer: "webapp",
inputKind: "Service",
inputName: "webapp",
inputHashedID: "1ba506b28f9ee9c7e8a0c98840fe5a1fe21142d225ecc526fbb535d0d6344aaf",
want: "service-webapp-webapp-1ba5-4aaf",
wantErr: nil,
},
{
name: "valid instanceID with different namespace name produces different hash",
inputNamespace: "blabla",
inputContainer: "webapp",
inputKind: "Service",
inputName: "webapp",
inputHashedID: "000006b28f9ee9c7e8a0c98840fe5a1fe21142d225ecc526fbb535d0d6340000",
want: "service-webapp-webapp-0000-0000",
wantErr: nil,
},
{
name: "instanceID that produces overflowing slugs gets truncated to limit",
inputNamespace: "default",
Expand All @@ -168,7 +189,7 @@ func TestInstanceIDToFriendlyName(t *testing.T) {

for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) {
got, err := InstanceIDToSlug(tc.inputName, tc.inputKind, tc.inputHashedID)
got, err := InstanceIDToSlug(tc.inputName, tc.inputKind, tc.inputContainer, tc.inputHashedID)

assert.Equal(t, tc.want, got)
assert.ErrorIs(t, err, tc.wantErr)
Expand Down

0 comments on commit e07cb7c

Please sign in to comment.