in pkg/provider/provider.go [117:266]
func (p *provider) GetSecretsStoreObjectContent(ctx context.Context, attrib, secrets map[string]string, defaultFilePermission os.FileMode) ([]types.SecretFile, error) {
keyvaultName := types.GetKeyVaultName(attrib)
cloudName := types.GetCloudName(attrib)
userAssignedIdentityID := types.GetUserAssignedIdentityID(attrib)
tenantID := types.GetTenantID(attrib)
cloudEnvFileName := types.GetCloudEnvFileName(attrib)
podName := types.GetPodName(attrib)
podNamespace := types.GetPodNamespace(attrib)
usePodIdentity, err := types.GetUsePodIdentity(attrib)
if err != nil {
return nil, fmt.Errorf("failed to parse usePodIdentity flag, error: %w", err)
}
useVMManagedIdentity, err := types.GetUseVMManagedIdentity(attrib)
if err != nil {
return nil, fmt.Errorf("failed to parse useVMManagedIdentity flag, error: %w", err)
}
// attributes for workload identity
workloadIdentityClientID := types.GetClientID(attrib)
saTokens := types.GetServiceAccountTokens(attrib)
if keyvaultName == "" {
return nil, fmt.Errorf("keyvaultName is not set")
}
if tenantID == "" {
return nil, fmt.Errorf("tenantId is not set")
}
err = setAzureEnvironmentFilePath(cloudEnvFileName)
if err != nil {
return nil, fmt.Errorf("failed to set AZURE_ENVIRONMENT_FILEPATH env to %s, error %w", cloudEnvFileName, err)
}
azureCloudEnv, err := p.parseAzureEnvironment(cloudName)
if err != nil {
return nil, fmt.Errorf("cloudName %s is not valid, error: %w", cloudName, err)
}
// parse bound service account tokens for workload identity only if the clientID is set
var workloadIdentityToken string
if workloadIdentityClientID != "" {
if workloadIdentityToken, err = auth.ParseServiceAccountToken(saTokens); err != nil {
return nil, fmt.Errorf("failed to parse workload identity tokens, error: %w", err)
}
}
authConfig, err := auth.NewConfig(usePodIdentity, useVMManagedIdentity, userAssignedIdentityID, workloadIdentityClientID, workloadIdentityToken, secrets)
if err != nil {
return nil, fmt.Errorf("failed to create auth config, error: %w", err)
}
mc := &mountConfig{
keyvaultName: keyvaultName,
azureCloudEnvironment: azureCloudEnv,
authConfig: authConfig,
tenantID: tenantID,
podName: podName,
podNamespace: podNamespace,
}
objectsStrings := types.GetObjects(attrib)
if objectsStrings == "" {
return nil, fmt.Errorf("objects is not set")
}
klog.V(2).InfoS("objects string defined in secret provider class", "objects", objectsStrings, "pod", klog.ObjectRef{Namespace: podNamespace, Name: podName})
objects, err := types.GetObjectsArray(objectsStrings)
if err != nil {
return nil, fmt.Errorf("failed to yaml unmarshal objects, error: %w", err)
}
klog.V(2).InfoS("unmarshaled objects yaml array", "objectsArray", objects.Array, "pod", klog.ObjectRef{Namespace: podNamespace, Name: podName})
keyVaultObjects := []types.KeyVaultObject{}
for i, object := range objects.Array {
var keyVaultObject types.KeyVaultObject
err = yaml.Unmarshal([]byte(object), &keyVaultObject)
if err != nil {
return nil, fmt.Errorf("unmarshal failed for keyVaultObjects at index %d, error: %w", i, err)
}
// remove whitespace from all fields in keyVaultObject
formatKeyVaultObject(&keyVaultObject)
if err = validate(keyVaultObject); err != nil {
return nil, wrapObjectTypeError(err, keyVaultObject.ObjectType, keyVaultObject.ObjectName, keyVaultObject.ObjectVersion)
}
keyVaultObjects = append(keyVaultObjects, keyVaultObject)
}
klog.V(5).InfoS("unmarshaled key vault objects", "keyVaultObjects", keyVaultObjects, "count", len(keyVaultObjects), "pod", klog.ObjectRef{Namespace: podNamespace, Name: podName})
if len(keyVaultObjects) == 0 {
return nil, nil
}
vaultURL, err := mc.getVaultURL()
if err != nil {
return nil, errors.Wrap(err, "failed to get vault")
}
klog.V(2).InfoS("vault url", "vaultName", mc.keyvaultName, "vaultURL", *vaultURL, "pod", klog.ObjectRef{Namespace: podNamespace, Name: podName})
// the keyvault name is per SPC and we don't need to recreate the client for every single keyvault object defined
kvClient, err := mc.initializeKvClient(*vaultURL)
if err != nil {
return nil, errors.Wrap(err, "failed to get keyvault client")
}
files := []types.SecretFile{}
for _, keyVaultObject := range keyVaultObjects {
klog.V(5).InfoS("fetching object from key vault", "objectName", keyVaultObject.ObjectName, "objectType", keyVaultObject.ObjectType, "keyvault", mc.keyvaultName, "pod", klog.ObjectRef{Namespace: podNamespace, Name: podName})
resolvedKvObjects, err := p.resolveObjectVersions(ctx, kvClient, keyVaultObject)
if err != nil {
return nil, err
}
for _, resolvedKvObject := range resolvedKvObjects {
// fetch the object from Key Vault
result, err := p.getKeyVaultObjectContent(ctx, kvClient, resolvedKvObject)
if err != nil {
return nil, err
}
for idx := range result {
r := result[idx]
objectContent, err := getContentBytes(r.content, resolvedKvObject.ObjectType, resolvedKvObject.ObjectEncoding)
if err != nil {
return nil, err
}
// objectUID is a unique identifier in the format <object type>/<object name>
// This is the object id the user sees in the SecretProviderClassPodStatus
objectUID := resolvedKvObject.GetObjectUID()
file := types.SecretFile{
Path: resolvedKvObject.GetFileName() + r.fileNameSuffix,
Content: objectContent,
UID: objectUID,
Version: r.version,
}
// the validity of file permission is already checked in the validate function above
file.FileMode, _ = resolvedKvObject.GetFilePermission(defaultFilePermission)
files = append(files, file)
klog.V(5).InfoS("added file to the gRPC response", "file", file.Path, "pod", klog.ObjectRef{Namespace: podNamespace, Name: podName})
}
}
}
return files, nil
}