Skip to content

Commit

Permalink
mod: support version as tail in versionHistory
Browse files Browse the repository at this point in the history
  • Loading branch information
duffney committed Dec 10, 2024
1 parent eada4d6 commit 3672ca0
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 32 deletions.
77 changes: 49 additions & 28 deletions pkg/keymanagementprovider/azurekeyvault/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,12 @@ func (s *akvKMProvider) GetCertificates(ctx context.Context) (map[keymanagementp
return nil, nil, fmt.Errorf("failed to get certificate objectName:%s, objectVersion:%s, error: %w", keyVaultCert.Name, keyVaultCert.Version, err)
}
certBundle := certResponse.CertificateBundle
keyVaultCert.Version = getObjectVersion(*certBundle.KID)
disabledVersion := getObjectVersion(*certBundle.KID)
isEnabled := *certBundle.Attributes.Enabled
lastRefreshed := startTime.Format(time.RFC3339)
certProperty := getStatusProperty(keyVaultCert.Name, keyVaultCert.Version, lastRefreshed, isEnabled)
certProperty := getStatusProperty(keyVaultCert.Name, disabledVersion, lastRefreshed, isEnabled)
certsStatus = append(certsStatus, certProperty)
mapKey := keymanagementprovider.KMPMapKey{Name: keyVaultCert.Name, Version: keyVaultCert.Version, Enabled: isEnabled}
mapKey := keymanagementprovider.KMPMapKey{Name: keyVaultCert.Name, Version: disabledVersion, Enabled: isEnabled}
keymanagementprovider.DeleteCertificateFromMap(s.resource, mapKey)
continue
}
Expand Down Expand Up @@ -273,23 +273,19 @@ func (s *akvKMProvider) GetCertificates(ctx context.Context) (map[keymanagementp
}
}

// Pager results are not sorted by created time, so we sort them here
// in ascending order (oldest to newest)
sortVersionHistory(versionHistory)
sortedVersionHistory := GetVersions(versionHistory)

if len(sortedVersionHistory) == 0 {
logger.GetLogger(ctx, logOpt).Infof("no versions found for certificate %s", keyVaultCert.Name)
versions, err := processVersionHistory(versionHistory, keyVaultCert.VersionHistoryLimit, keyVaultCert.Version)
if err != nil {
logger.GetLogger(ctx, logOpt).Errorf("failed to process version history for certificate %s: %v", keyVaultCert.Name, err)
continue

Check warning on line 279 in pkg/keymanagementprovider/azurekeyvault/provider.go

View check run for this annotation

Codecov / codecov/patch

pkg/keymanagementprovider/azurekeyvault/provider.go#L278-L279

Added lines #L278 - L279 were not covered by tests
}

// Ensure that the versionHistoryLimit is not greater than the number of versions to avoid out of bounds error
if keyVaultCert.VersionHistoryLimit > len(sortedVersionHistory) {
keyVaultCert.VersionHistoryLimit = len(sortedVersionHistory)
if len(versions) == 0 {
logger.GetLogger(ctx, logOpt).Infof("no versions found for certificate %s", keyVaultCert.Name)
continue
}

// get the latest version of the certificate up to the limit
for _, version := range sortedVersionHistory[len(sortedVersionHistory)-keyVaultCert.VersionHistoryLimit:] {
for _, version := range versions {
secretReponse, err := s.secretKVClient.GetSecret(ctx, keyVaultCert.Name, version)
if err != nil {
if isSecretDisabledError(err) {
Expand Down Expand Up @@ -393,24 +389,18 @@ func (s *akvKMProvider) GetKeys(ctx context.Context) (map[keymanagementprovider.
}
}

// Pager results are not sorted by created time, so we sort them here
// in ascending order (oldest to newest)
sortVersionHistory(versionHistory)
sortedVersionHistory := GetVersions(versionHistory)

// if no versions found, log and continue
if len(sortedVersionHistory) == 0 {
logger.GetLogger(ctx, logOpt).Infof("no versions found for key %s", keyVaultKey.Name)
versions, err := processVersionHistory(versionHistory, keyVaultKey.VersionHistoryLimit, keyVaultKey.Version)
if err != nil {
logger.GetLogger(ctx, logOpt).Errorf("failed to process version history for key %s: %v", keyVaultKey.Name, err)
continue

Check warning on line 395 in pkg/keymanagementprovider/azurekeyvault/provider.go

View check run for this annotation

Codecov / codecov/patch

pkg/keymanagementprovider/azurekeyvault/provider.go#L394-L395

Added lines #L394 - L395 were not covered by tests
}

// if versionHistoryLimit is greater than the number of versions, set it to the number of versions
if keyVaultKey.VersionHistoryLimit > len(sortedVersionHistory) {
keyVaultKey.VersionHistoryLimit = len(sortedVersionHistory)
if len(versions) == 0 {
logger.GetLogger(ctx, logOpt).Infof("no versions found for key %s", keyVaultKey.Name)
continue
}

// get the latest version of the certificate up to the limit
for _, version := range sortedVersionHistory[len(sortedVersionHistory)-keyVaultKey.VersionHistoryLimit:] {
for _, version := range versions {
keyResponse, err := s.keyKVClient.GetKey(ctx, keyVaultKey.Name, version)
if err != nil {
return nil, nil, fmt.Errorf("failed to get key objectName:%s, objectVersion:%s, error: %w", keyVaultKey.Name, version, err)
Expand Down Expand Up @@ -658,6 +648,37 @@ func isSecretDisabledError(err error) bool {
return false
}

// processVersionHistory returns the versions of the object based on the versionHistoryLimit and version
func processVersionHistory(versionHistory []VersionInfo, versionHistoryLimit int, version string) (versions []string, err error) {
sortVersionHistory(versionHistory)

if version == "" {
//Ensure that the versionHistoryLimit is not greater than the number of versions to avoid out of bounds error
if versionHistoryLimit > len(versionHistory) {
versionHistoryLimit = len(versionHistory)
}
return getVersions(versionHistory[len(versionHistory)-versionHistoryLimit:]), nil
}
// Find the index of the specified version
versionIndex := -1
for i, v := range versionHistory {
if v.Version == version {
versionIndex = i
break
}
}

// Calculate the start index to include up to `versionHistoryLimit` older versions
start := versionIndex - versionHistoryLimit
if start < 0 {
start = 0 // Ensure we don't go out of bounds
}

// Create the slice including the specified version as the tail
return getVersions(versionHistory[start : versionIndex+1]), nil

}

Check failure on line 680 in pkg/keymanagementprovider/azurekeyvault/provider.go

View workflow job for this annotation

GitHub Actions / lint

unnecessary trailing newline (whitespace)

// sortVersionHistory sorts the version history by created time
func sortVersionHistory(sortedVersionHistory []VersionInfo) {
sort.Slice(sortedVersionHistory, func(i, j int) bool {
Expand All @@ -666,7 +687,7 @@ func sortVersionHistory(sortedVersionHistory []VersionInfo) {
}

// GetVersions returns the sorted versions of the object
func GetVersions(versionHistory []VersionInfo) []string {
func getVersions(versionHistory []VersionInfo) []string {
sortedVersions := make([]string, 0, len(versionHistory))
for _, version := range versionHistory {
sortedVersions = append(sortedVersions, version.Version)
Expand Down
29 changes: 25 additions & 4 deletions pkg/keymanagementprovider/azurekeyvault/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,11 +303,14 @@ func boolPtr(b bool) *bool {
func TestGetCertificates(t *testing.T) {
certID := azcertificates.ID("https://testkv.vault.azure.net/certificates/cert1/d47a1c09f5b6437da28e9c72b1f4e0fd")
certIDCreated := time.Now()
certIDmiddle := azcertificates.ID("https://testkv.vault.azure.net/certificates/cert1/a1f03df1113d460491d970737dfdc35d")
certIDmiddleCreated := time.Now().Add(1 * time.Minute)
certIDLatest := azcertificates.ID("https://testkv.vault.azure.net/certificates/cert1/8f2e5a13c4b74960d7a8e2f1c0d6b3a9")
certIDLatestCreated := time.Now().Add(1 * time.Minute)
certIDLatestCreated := time.Now().Add(2 * time.Minute)
secretID := azsecrets.ID("https://testkv.vault.azure.net/secrets/secret1")
testCases := []struct {
name string
version string
versionHistoryLimit int
mockKeyKVClient *MockKeyKVClient
mockSecretKVClient *MockSecretKVClient
Expand Down Expand Up @@ -502,8 +505,9 @@ func TestGetCertificates(t *testing.T) {
expectedErr: false,
},
{
name: "FetchVersionHistory: Certificate enabled with multiple versions",
versionHistoryLimit: 3,
name: "FetchVersionHistory: Certificate enabled with multiple versions(test version specified)",
version: "a1f03df1113d460491d970737dfdc35d",
versionHistoryLimit: 1,
mockCertificateKVClient: &MockCertificateKVClient{
GetCertificateFunc: func(_ context.Context, _ string, _ string) (azcertificates.GetCertificateResponse, error) {
return azcertificates.GetCertificateResponse{
Expand Down Expand Up @@ -540,6 +544,23 @@ func TestGetCertificates(t *testing.T) {
}

if pageCounter == 1 {
resp = azcertificates.ListCertificateVersionsResponse{
CertificateListResult: azcertificates.CertificateListResult{
NextLink: stringPtr("https://testkv.vault.azure.net/certificates/cert1/versions?api-version=7.2"),
Value: []*azcertificates.CertificateItem{
{
ID: &certIDmiddle,
Attributes: &azcertificates.CertificateAttributes{
Enabled: boolPtr(true),
Created: &certIDmiddleCreated,
},
},
},
},
}
}

if pageCounter == 2 {
resp = azcertificates.ListCertificateVersionsResponse{
CertificateListResult: azcertificates.CertificateListResult{
NextLink: nil,
Expand Down Expand Up @@ -699,7 +720,7 @@ func TestGetCertificates(t *testing.T) {
certificates: []types.KeyVaultValue{
{
Name: "cert1",
Version: "c1f03df1113d460491d970737dfdc35d",
Version: tc.version,
VersionHistoryLimit: tc.versionHistoryLimit,
},
},
Expand Down

0 comments on commit 3672ca0

Please sign in to comment.