From c66719dd8fa4698e3c4fd57cb4090f5d1984f4e3 Mon Sep 17 00:00:00 2001 From: Craig Spencer Date: Wed, 24 Jul 2024 14:20:08 -0700 Subject: [PATCH] Co-authored-by: madhavilosetty-intel --- internal/local/ethernet.go | 11 +- internal/local/lps_test.go | 13 +- internal/local/pruneCerts.go | 233 +----------------------------- internal/local/pruneCerts_test.go | 75 +++++++++- internal/local/wifi.go | 2 +- 5 files changed, 88 insertions(+), 246 deletions(-) diff --git a/internal/local/ethernet.go b/internal/local/ethernet.go index 94f0c633..202a0b52 100644 --- a/internal/local/ethernet.go +++ b/internal/local/ethernet.go @@ -2,7 +2,6 @@ package local import ( "errors" - "fmt" "os" "rpc/internal/config" "rpc/pkg/utils" @@ -108,7 +107,7 @@ func (service *ProvisioningService) PruneEthernetConfigs() (err error) { } } - _, err = service.PruneCerts(certHandles, keyPairHandles) + service.PruneCerts(certHandles, keyPairHandles) return err } @@ -281,13 +280,7 @@ func (service *ProvisioningService) AddCerts(handles Handles, ieee8021xConfig co handles.privateKeyHandle, err = service.interfacedWsmanMessage.AddPrivateKey(ieee8021xConfig.PrivateKey) service.handlesWithCerts[handles.privateKeyHandle] = ieee8021xConfig.PrivateKey if err != nil && strings.Contains(err.Error(), "already exists") { - - securitySettings, err := service.GetCertRelationships() - if err != nil { - return handles, err - } - fmt.Println(securitySettings) - + // handles.privateKeyHandle, _ = service.GetPrivKeyHandle(ieee8021xConfig.PrivateKey) } else if err != nil { return handles, err } diff --git a/internal/local/lps_test.go b/internal/local/lps_test.go index 8c512c06..2b0edf2a 100644 --- a/internal/local/lps_test.go +++ b/internal/local/lps_test.go @@ -306,15 +306,16 @@ func (m MockWSMAN) HostBasedSetupServiceAdmin(password string, digestRealm strin return mockHostBasedSetupServiceAdmin, errHostBasedSetupServiceAdmin } +var mockGetPublicKeyCertsResponse = []publickey.PublicKeyCertificateResponse{} var errGetPublicKeyCerts error = nil func (m MockWSMAN) GetPublicKeyCerts() ([]publickey.PublicKeyCertificateResponse, error) { - certs := []publickey.PublicKeyCertificateResponse{ - mpsCert, - clientCert, - caCert, - } - return certs, errGetPublicKeyCerts + // certs := []publickey.PublicKeyCertificateResponse{ + // mpsCert, + // clientCert, + // caCert, + // } + return mockGetPublicKeyCertsResponse, errGetPublicKeyCerts } var errGetPublicPrivateKeyPairs error = nil diff --git a/internal/local/pruneCerts.go b/internal/local/pruneCerts.go index bec70534..219d1efd 100644 --- a/internal/local/pruneCerts.go +++ b/internal/local/pruneCerts.go @@ -1,229 +1,27 @@ package local import ( - // "rpc/pkg/utils" - - "reflect" - "strings" - log "github.com/sirupsen/logrus" - - "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/publickey" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/publicprivate" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/concrete" - "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/cim/credential" ) -const ( - TypeWireless string = "Wireless" - TypeTLS string = "TLS" - TypeWired string = "Wired" -) - -type ( - SecuritySettings struct { - ProfileAssociation []ProfileAssociation `json:"ProfileAssociation"` - Certificates interface{} `json:"Certificates"` - Keys interface{} `json:"PublicKeys"` - } - - ProfileAssociation struct { - Type string `json:"Type"` - ProfileID string `json:"ProfileID"` - RootCertificate interface{} `json:"RootCertificate,omitempty"` - ClientCertificate interface{} `json:"ClientCertificate,omitempty"` - Key interface{} `json:"PublicKey,omitempty"` - } -) - -func (service *ProvisioningService) PruneCerts(certHandles []string, keyPairHandles []string) (certsInUse []string, err error) { +func (service *ProvisioningService) PruneCerts(certHandles []string, keyPairHandles []string) (certsInUse []string) { for _, handle := range certHandles { - err = service.interfacedWsmanMessage.DeletePublicCert(handle) + err := service.interfacedWsmanMessage.DeletePublicCert(handle) if err != nil { - log.Infof("unable to delete: %s %s", handle, err) - // err = utils.DeleteConfigsFailed + log.Debugf("unable to delete: %s %s", handle, err) certsInUse = append(certsInUse, handle) } else { delete(service.handlesWithCerts, handle) } } for _, handle := range keyPairHandles { - err = service.interfacedWsmanMessage.DeletePublicPrivateKeyPair(handle) + err := service.interfacedWsmanMessage.DeletePublicPrivateKeyPair(handle) if err != nil { - log.Infof("unable to delete: %s %s", handle, err) - // err = utils.DeleteConfigsFailed + log.Debugf("unable to delete: %s %s", handle, err) certsInUse = append(certsInUse, handle) } } - return certsInUse, nil // look into it again -} - -func processConcreteDependencies(certificateHandle string, profileAssociation *ProfileAssociation, dependancyItems []concrete.ConcreteDependency, keyPairItems []publicprivate.PublicPrivateKeyPair) { - for x := range dependancyItems { - if dependancyItems[x].Antecedent.ReferenceParameters.SelectorSet.Selectors[0].Text != certificateHandle { - continue - } - - keyHandle := dependancyItems[x].Dependent.ReferenceParameters.SelectorSet.Selectors[0].Text - - for i := range keyPairItems { - if keyPairItems[i].InstanceID == keyHandle { - profileAssociation.Key = keyPairItems[i] - - break - } - } - } -} - -func buildCertificateAssociations(profileAssociation ProfileAssociation, securitySettings *SecuritySettings) { - var publicKeyHandle string - - // If a client cert, update the associated public key w/ the cert's handle - if profileAssociation.ClientCertificate != nil { - // Loop thru public keys looking for the one that matches the current profileAssociation's key - for i, existingKeyPair := range securitySettings.Keys.(publicprivate.RefinedPullResponse).PublicPrivateKeyPairItems { - // If found update that key with the profileAssociation's certificate handle - if existingKeyPair.InstanceID == profileAssociation.Key.(publicprivate.RefinedPublicPrivateKeyPair).InstanceID { - securitySettings.Keys.(publicprivate.RefinedPullResponse).PublicPrivateKeyPairItems[i].CertificateHandle = profileAssociation.ClientCertificate.(publickey.RefinedPublicKeyCertificateResponse).InstanceID - // save this public key handle since we know it pairs with the profileAssociation's certificate - publicKeyHandle = securitySettings.Keys.(publicprivate.RefinedPullResponse).PublicPrivateKeyPairItems[i].InstanceID - - break - } - } - } - - // Loop thru certificates looking for the one that matches the current profileAssociation's certificate and append profile name - for i := range securitySettings.Certificates.(publickey.RefinedPullResponse).PublicKeyCertificateItems { - if (profileAssociation.ClientCertificate != nil && securitySettings.Certificates.(publickey.RefinedPullResponse).PublicKeyCertificateItems[i].InstanceID == profileAssociation.ClientCertificate.(publickey.RefinedPublicKeyCertificateResponse).InstanceID) || - (profileAssociation.RootCertificate != nil && securitySettings.Certificates.(publickey.RefinedPullResponse).PublicKeyCertificateItems[i].InstanceID == profileAssociation.RootCertificate.(publickey.RefinedPublicKeyCertificateResponse).InstanceID) { - // if client cert found, associate the previously found key handle with it - if !securitySettings.Certificates.(publickey.RefinedPullResponse).PublicKeyCertificateItems[i].TrustedRootCertificate { - securitySettings.Certificates.(publickey.RefinedPullResponse).PublicKeyCertificateItems[i].PublicKeyHandle = publicKeyHandle - } - - securitySettings.Certificates.(publickey.RefinedPullResponse).PublicKeyCertificateItems[i].AssociatedProfiles = append(securitySettings.Certificates.(publickey.RefinedPullResponse).PublicKeyCertificateItems[i].AssociatedProfiles, profileAssociation.ProfileID) - - break - } - } -} - -func buildProfileAssociations(certificateHandle string, profileAssociation *ProfileAssociation, response Certificates, securitySettings *SecuritySettings) { - isNewProfileAssociation := true - - for idx := range response.PublicKeyCertificateResponse { - if response.PublicKeyCertificateResponse[idx].InstanceID != certificateHandle { - continue - } - - if response.PublicKeyCertificateResponse[idx].TrustedRootCertificate { - profileAssociation.RootCertificate = response.PublicKeyCertificateResponse[idx] - - continue - } - - profileAssociation.ClientCertificate = response.PublicKeyCertificateResponse[idx] - - processConcreteDependencies(certificateHandle, profileAssociation, response.ConcreteDependencyResponse, response.PublicPrivateKeyPairResponse) - } - - // Check if the certificate is already in the list - for idx := range securitySettings.ProfileAssociation { - if !(securitySettings.ProfileAssociation[idx].ProfileID == profileAssociation.ProfileID) { - continue - } - - if profileAssociation.RootCertificate != nil { - securitySettings.ProfileAssociation[idx].RootCertificate = profileAssociation.RootCertificate - } - - if profileAssociation.ClientCertificate != nil { - securitySettings.ProfileAssociation[idx].ClientCertificate = profileAssociation.ClientCertificate - } - - if profileAssociation.Key != nil { - securitySettings.ProfileAssociation[idx].Key = profileAssociation.Key - } - - isNewProfileAssociation = false - - break - } - - // If the profile is not in the list, add it - if isNewProfileAssociation { - securitySettings.ProfileAssociation = append(securitySettings.ProfileAssociation, *profileAssociation) - } -} - -func processCertificates(contextItems []credential.CredentialContext, response Certificates, profileType string, securitySettings *SecuritySettings) { - for idx := range contextItems { - var profileAssociation ProfileAssociation - - profileAssociation.Type = profileType - profileAssociation.ProfileID = strings.TrimPrefix(contextItems[idx].ElementProvidingContext.ReferenceParameters.SelectorSet.Selectors[0].Text, "Intel(r) AMT:IEEE 802.1x Settings ") - certificateHandle := contextItems[idx].ElementInContext.ReferenceParameters.SelectorSet.Selectors[0].Text - - buildProfileAssociations(certificateHandle, &profileAssociation, response, securitySettings) - buildCertificateAssociations(profileAssociation, securitySettings) - } -} - -type Certificates struct { - ConcreteDependencyResponse []concrete.ConcreteDependency - PublicKeyCertificateResponse []publickey.PublicKeyCertificateResponse - PublicPrivateKeyPairResponse []publicprivate.PublicPrivateKeyPair - CIMCredentialContextResponse credential.Items -} - -func (service *ProvisioningService) GetCertRelationships() (SecuritySettings, error) { - response, err := service.GetCertificates() - if err != nil { - return SecuritySettings{}, err - } - - securitySettings := SecuritySettings{ - Certificates: response.PublicKeyCertificateResponse, - Keys: response.PublicPrivateKeyPairResponse, - } - - if !reflect.DeepEqual(response.CIMCredentialContextResponse, credential.PullResponse{}) { - processCertificates(response.CIMCredentialContextResponse.CredentialContextTLS, response, TypeTLS, &securitySettings) - processCertificates(response.CIMCredentialContextResponse.CredentialContext, response, TypeWireless, &securitySettings) - processCertificates(response.CIMCredentialContextResponse.CredentialContext8021x, response, TypeWired, &securitySettings) - } - - return securitySettings, nil -} - -func (service *ProvisioningService) GetCertificates() (Certificates, error) { - concreteDepResponse, err := service.interfacedWsmanMessage.GetConcreteDependencies() - if err != nil { - return Certificates{}, err - } - pubKeyCertResponse, err := service.interfacedWsmanMessage.GetPublicKeyCerts() - if err != nil { - return Certificates{}, err - } - pubPrivKeyPairResponse, err := service.interfacedWsmanMessage.GetPublicPrivateKeyPairs() - if err != nil { - return Certificates{}, err - } - cimCredContextResponse, err := service.interfacedWsmanMessage.GetCredentialRelationships() - if err != nil { - return Certificates{}, err - } - - certificates := Certificates{ - ConcreteDependencyResponse: concreteDepResponse, - PublicKeyCertificateResponse: pubKeyCertResponse, - PublicPrivateKeyPairResponse: pubPrivKeyPairResponse, - CIMCredentialContextResponse: cimCredContextResponse, - } - - return certificates, nil + return certsInUse } func (service *ProvisioningService) PruneTLSCerts() (err error) { @@ -239,7 +37,7 @@ func (service *ProvisioningService) PruneTLSCerts() (err error) { } var empty []string - certsInUse, err := service.PruneCerts(handlesToDelete, empty) + certsInUse := service.PruneCerts(handlesToDelete, empty) if err != nil { return err } @@ -250,23 +48,6 @@ func (service *ProvisioningService) PruneTLSCerts() (err error) { return nil - // credentialRelationships, err := service.interfacedWsmanMessage.GetCredentialRelationships() - // if err != nil { - // return err - // } - - // Warn users about certificates that are in use - - // for _, credentialContext := range credentialRelationships.CredentialContextTLS { - // inParams := credentialContext.ElementInContext.ReferenceParameters - // id := inParams.GetSelectorValue("InstanceID") - // handlesToDelete = append(handlesToDelete, id) - // } - - // service.DisableTLS() - - // fmt.Print(publicCerts, credentialRelationships) - } // func (service *ProvisioningService) DisableTLS(handle string) (err error) { diff --git a/internal/local/pruneCerts_test.go b/internal/local/pruneCerts_test.go index 88a28c23..5de69108 100644 --- a/internal/local/pruneCerts_test.go +++ b/internal/local/pruneCerts_test.go @@ -1,9 +1,13 @@ package local import ( + "bytes" "rpc/internal/flags" + "rpc/pkg/utils" "testing" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/wsman/amt/publickey" + log "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" ) @@ -19,12 +23,66 @@ func TestPruneCerts(t *testing.T) { name: "successful pruning", expectedError: false, }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + f := &flags.Flags{} + mockAMT := new(MockAMT) + mockWsman := new(MockWSMAN) + service := NewProvisioningService(f) + service.amtCommand = mockAMT + service.interfacedWsmanMessage = mockWsman + + service.PruneCerts(certHandles, keyPairHandles) + }) + } +} + +func TestPruneTLSCerts(t *testing.T) { + tests := []struct { + name string + setupMocks func(*MockWSMAN) + expectWarning bool + expectedError bool + }{ { - name: "fails to delete public cert", - expectedError: true, + name: "successful pruning", + setupMocks: func(mock *MockWSMAN) { + mockGetPublicKeyCertsResponse = []publickey.PublicKeyCertificateResponse{ + { + InstanceID: "handle 1", + }, + { + InstanceID: "handle 2", + }, + } + }, + expectWarning: false, + expectedError: false, }, { - name: "fails to delete private key pair", + name: "fails to delete cert", + setupMocks: func(mock *MockWSMAN) { + mockGetPublicKeyCertsResponse = []publickey.PublicKeyCertificateResponse{ + { + InstanceID: "handle 1", + }, + { + InstanceID: "handle 3", + }, + } + errDeletePublicCert = utils.GenericFailure + }, + expectWarning: true, + expectedError: false, + }, + { + name: "fails to get certs", + setupMocks: func(mock *MockWSMAN) { + errGetPublicKeyCerts = utils.GenericFailure + }, + expectWarning: false, expectedError: true, }, } @@ -37,14 +95,23 @@ func TestPruneCerts(t *testing.T) { service := NewProvisioningService(f) service.amtCommand = mockAMT service.interfacedWsmanMessage = mockWsman + tc.setupMocks(mockWsman) - _, err := service.PruneCerts(certHandles, keyPairHandles) + // Setup a buffer to capture log output + var buf bytes.Buffer + log.SetOutput(&buf) + + err := service.PruneTLSCerts() if tc.expectedError { assert.Error(t, err) } else { assert.NoError(t, err) } + + if tc.expectWarning { + assert.Contains(t, buf.String(), "The following certs are in use and cannot be deleted:") + } }) } } diff --git a/internal/local/wifi.go b/internal/local/wifi.go index 292333e0..af94dd26 100644 --- a/internal/local/wifi.go +++ b/internal/local/wifi.go @@ -72,7 +72,7 @@ func (service *ProvisioningService) PruneWifiConfigs() (err error) { log.Infof("successfully deleted wifiSetting: %s", wifiSetting.InstanceID) } - _, err = service.PruneCerts(certHandles, keyPairHandles) + service.PruneCerts(certHandles, keyPairHandles) return err }