in pkg/cmd/podidentity/detect.go [130:233]
func (dc *detectCmd) run() error {
mlog.Debug("detecting aad-pod-identity configuration", "namespace", dc.namespace)
// Implementing force namespaced mode
// 1. Get AzureIdentityBinding in the namespace
// 2. Get AzureIdentity referenced by AzureIdentityBinding and store in map with aadpodidbinding label value as key and AzureIdentity as value
// 3. Get all pods in the namespace that have aadpodidbinding label
// 4. For each pod, check if there is an owner reference (deployment, statefulset, cronjob, job, daemonset, replicaset, replicationcontroller)
// 5. If there is an owner reference, get the owner reference object and add to map with aadpodidbinding label value as key and owner reference as value
// 6. If no owner reference, then assume it's a static pod and add to map with aadpodidbinding label value as key and pod as value
// 7. Loop through the first map and generate new config file for each owner reference and service account
// 1. If owner is using a service account, get the service account and generate a config file with it
// 2. If owner doesn't use service account, generate a new service account yaml file with owner name as service account name
azureIdentityBindings, err := kuberneteshelper.ListAzureIdentityBinding(context.TODO(), dc.kubeClient, dc.namespace)
if err != nil {
return err
}
azureIdentities, err := kuberneteshelper.ListAzureIdentity(context.TODO(), dc.kubeClient, dc.namespace)
if err != nil {
return err
}
azureIdentityMap := make(map[string]aadpodv1.AzureIdentity)
for _, azureIdentity := range azureIdentities {
if azureIdentity.Spec.Type == aadpodv1.UserAssignedMSI {
azureIdentityMap[azureIdentity.Name] = azureIdentity
}
}
labelsToAzureIdentityMap := filterAzureIdentities(azureIdentityBindings, azureIdentityMap)
if count := len(labelsToAzureIdentityMap); count > 0 {
mlog.Debug("found valid aad-pod-identity bindings", "count", count)
} else {
mlog.Debug("did not find any valid aad-pod-identity bindings")
}
ownerReferences := make(map[metav1.OwnerReference]string)
results := make(map[client.Object]string)
for selector, azureIdentity := range labelsToAzureIdentityMap {
mlog.Debug("getting pods", "selector", selector)
pods, err := kuberneteshelper.ListPods(context.TODO(), dc.kubeClient, dc.namespace, map[string]string{aadpodv1.CRDLabelKey: selector})
if err != nil {
return err
}
for i := range pods {
// for pods created by higher level constructors like deployment, statefulset, cronjob, job, daemonset, replicaset, replicationcontroller
// we can get the owner reference with pod.OwnerReferences
ownerFound := false
if len(pods[i].OwnerReferences) > 0 {
for _, ownerReference := range pods[i].OwnerReferences {
// only get the owner reference that was set by the parent controller
if ownerReference.Controller != nil && *ownerReference.Controller {
ownerReferences[ownerReference] = azureIdentity.Spec.ClientID
ownerFound = true
break
}
}
}
// this is a standalone pod, so add it to the results
if !ownerFound {
p := pods[i]
results[&p] = azureIdentity.Spec.ClientID
}
}
}
for ownerReference, clientID := range ownerReferences {
owner, err := dc.getOwner(ownerReference)
if err != nil {
return err
}
results[owner] = clientID
}
// results contains all the resources that we need to generate a config file.
// for each entry in the results map, we will generate a service account yaml file
// and a resource file
for o, clientID := range results {
localObject := k8s.NewLocalObject(o)
sa, err := dc.createServiceAccountFile(localObject.GetServiceAccountName(), localObject.GetName(), clientID)
if err != nil {
return err
}
if err = dc.createResourceFile(localObject, sa); err != nil {
return err
}
mlog.Debug("generated config",
"kind", strings.ToLower(localObject.GetObjectKind().GroupVersionKind().Kind),
"name", localObject.GetName(),
"clientID", clientID,
)
}
if len(results) == 0 {
mlog.Debug("no aad-pod-identity configuration found", "namespace", dc.namespace)
return nil
}
mlog.Info("generated resource and service account files", "directory", dc.outputDir)
mlog.Info(nextStepsLogMessage)
return nil
}