Skip to content

Commit

Permalink
feat: Support ServiceAccount relationships
Browse files Browse the repository at this point in the history
Remove `RelationshipPodServiceAccount` as there isn't exactly a direct
relationship between Pods & ServiceAccounts, but rather Pods and
ServiceAccount tokens.

Removing this would also make the command output cleaner when we run
`kubectl-lineage serviceaccount $SERVICE_ACCOUNT_NAME` as we won't
see the pod appearing twice in the output.

If `RelationshipPodServiceAccount` wasn't removed:

```shell
$ kubectl-lineage serviceaccount traefik -o wide
NAME                                  READY   STATUS    AGE   RELATIONSHIPS
ServiceAccount/traefik                -                 1d    -
├─  Pod/traefik-XXXXXXXXX-XXXXX       1/1     Running   1d    [PodServiceAccount]
└── Secret/traefik-token-XXXXX        -                 1d    [ServiceAccountSecret]
    └── Pod/traefik-XXXXXXXXX-XXXXX   1/1     Running   1d    [PodVolume]
```

Now:

```shell
$ kubectl-lineage serviceaccount traefik -o wide
NAME                                  READY   STATUS    AGE   RELATIONSHIPS
ServiceAccount/traefik                -                 1d    -
└── Secret/traefik-token-XXXXX        -                 1d    [ServiceAccountSecret]
    └── Pod/traefik-XXXXXXXXX-XXXXX   1/1     Running   1d    [PodVolume]
```

Signed-off-by: Justin Toh <tohjustin@hotmail.com>
  • Loading branch information
tohjustin committed Sep 28, 2021
1 parent a3044b0 commit cb164aa
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 5 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ List of supported relationships used for discovering dependent objects:
- [Controller References](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/controller-ref.md) & [Owner References](https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/)
- [Event References](https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/event-v1/)
- [Pod References](https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/)
- [ServiceAccount References](https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/service-account-v1/)
- Helm (Coming Soon)

## Installation
Expand Down
45 changes: 40 additions & 5 deletions pkg/cmd/lineage/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,11 @@ const (
RelationshipPodNode Relationship = "PodNode"
RelationshipPodPriorityClass Relationship = "PodPriorityClass"
RelationshipPodRuntimeClass Relationship = "PodRuntimeClass"
RelationshipPodServiceAccount Relationship = "PodServiceAccount"
RelationshipPodVolume Relationship = "PodVolume"

// Kubernetes ServiceAccount relationships.
RelationshipServiceAccountSecret Relationship = "ServiceAccountSecret"
RelationshipServiceAccountImagePullSecret Relationship = "ServiceAccountImagePullSecret"
)

// resolveDependents resolves all dependents of the provided root object and
Expand Down Expand Up @@ -259,6 +262,13 @@ func resolveDependents(objects []unstructuredv1.Unstructured, rootUID types.UID)
klog.V(4).Infof("Failed to get relationships for pod named \"%s\" in namespace \"%s\": %s", node.Name, node.Namespace, err)
continue
}
// Populate dependents based on ServiceAccount relationships
case node.Group == "" && node.Kind == "ServiceAccount":
rmap, err = getServiceAccountRelationships(node)
if err != nil {
klog.V(4).Infof("Failed to get relationships for serviceaccount named \"%s\" in namespace \"%s\": %s", node.Name, node.Namespace, err)
continue
}
default:
continue
}
Expand Down Expand Up @@ -388,10 +398,6 @@ func getPodRelationships(n *Node) (*RelationshipMap, error) {
result.AddDependencyByKey(ref.Key(), RelationshipPodRuntimeClass)
}

// RelationshipPodServiceAccount
ref = ObjectReference{Kind: "ServiceAccount", Name: pod.Spec.ServiceAccountName, Namespace: ns}
result.AddDependencyByKey(ref.Key(), RelationshipPodServiceAccount)

// RelationshipPodVolume
for _, v := range pod.Spec.Volumes {
switch {
Expand Down Expand Up @@ -420,3 +426,32 @@ func getPodRelationships(n *Node) (*RelationshipMap, error) {

return &result, nil
}

// getServiceAccountRelationships returns a map of relationships that this
// ServiceAccount has with other objects, based on what was referenced in its
// manifest.
func getServiceAccountRelationships(n *Node) (*RelationshipMap, error) {
var sa corev1.ServiceAccount
err := runtime.DefaultUnstructuredConverter.FromUnstructured(n.UnstructuredContent(), &sa)
if err != nil {
return nil, err
}

var ref ObjectReference
ns := sa.Namespace
result := newRelationshipMap()

// RelationshipServiceAccountImagePullSecret
for _, s := range sa.ImagePullSecrets {
ref = ObjectReference{Kind: "Secret", Name: s.Name, Namespace: ns}
result.AddDependencyByKey(ref.Key(), RelationshipServiceAccountImagePullSecret)
}

// RelationshipServiceAccountSecret
for _, s := range sa.Secrets {
ref = ObjectReference{Kind: "Secret", Name: s.Name, Namespace: ns}
result.AddDependentByKey(ref.Key(), RelationshipServiceAccountSecret)
}

return &result, nil
}

0 comments on commit cb164aa

Please sign in to comment.