-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
41 changed files
with
2,175 additions
and
96 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
package checker | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/tufin/oasdiff/diff" | ||
) | ||
|
||
const ( | ||
APISecurityRemovedCheckId = "api-security-removed" | ||
APISecurityAddedCheckId = "api-security-added" | ||
APISecurityScopeAddedId = "api-security-scope-added" | ||
APISecurityScopeRemovedId = "api-security-scope-removed" | ||
APIGlobalSecurityRemovedCheckId = "api-global-security-removed" | ||
APIGlobalSecurityAddedCheckId = "api-global-security-added" | ||
APIGlobalSecurityScopeAddedId = "api-global-security-scope-added" | ||
APIGlobalSecurityScopeRemovedId = "api-global-security-scope-removed" | ||
) | ||
|
||
func checkGlobalSecurity(diffReport *diff.Diff, operationsSources *diff.OperationsSourcesMap, config BackwardCompatibilityCheckConfig) []BackwardCompatibilityError { | ||
result := make([]BackwardCompatibilityError, 0) | ||
if diffReport.SecurityDiff == nil { | ||
return result | ||
} | ||
|
||
for _, addedSecurity := range diffReport.SecurityDiff.Added { | ||
result = append(result, BackwardCompatibilityError{ | ||
Id: APIGlobalSecurityAddedCheckId, | ||
Level: INFO, | ||
Text: fmt.Sprintf(config.i18n(APIGlobalSecurityAddedCheckId), ColorizedValue(addedSecurity)), | ||
Operation: "N/A", | ||
Path: "", | ||
Source: "security." + addedSecurity, | ||
OperationId: "N/A", | ||
}) | ||
} | ||
|
||
for _, removedSecurity := range diffReport.SecurityDiff.Deleted { | ||
result = append(result, BackwardCompatibilityError{ | ||
Id: APIGlobalSecurityRemovedCheckId, | ||
Level: INFO, | ||
Text: fmt.Sprintf(config.i18n(APIGlobalSecurityRemovedCheckId), ColorizedValue(removedSecurity)), | ||
Operation: "N/A", | ||
Path: "", | ||
Source: "security." + removedSecurity, | ||
OperationId: "N/A", | ||
}) | ||
} | ||
|
||
for _, updatedSecurity := range diffReport.SecurityDiff.Modified { | ||
for securitySchemeName, updatedSecuritySchemeScopes := range updatedSecurity { | ||
for _, addedScope := range updatedSecuritySchemeScopes.Added { | ||
result = append(result, BackwardCompatibilityError{ | ||
Id: APIGlobalSecurityScopeAddedId, | ||
Level: INFO, | ||
Text: fmt.Sprintf(config.i18n(APIGlobalSecurityScopeAddedId), ColorizedValue(addedScope), ColorizedValue(securitySchemeName)), | ||
Operation: "N/A", | ||
Path: "", | ||
Source: "security.scopes." + addedScope, | ||
OperationId: "N/A", | ||
}) | ||
} | ||
for _, deletedScope := range updatedSecuritySchemeScopes.Deleted { | ||
result = append(result, BackwardCompatibilityError{ | ||
Id: APIGlobalSecurityScopeRemovedId, | ||
Level: INFO, | ||
Text: fmt.Sprintf(config.i18n(APIGlobalSecurityScopeRemovedId), ColorizedValue(deletedScope), ColorizedValue(securitySchemeName)), | ||
Operation: "N/A", | ||
Path: "", | ||
Source: "security.scopes." + deletedScope, | ||
OperationId: "N/A", | ||
}) | ||
} | ||
} | ||
} | ||
|
||
return result | ||
|
||
} | ||
|
||
func APISecurityUpdatedCheck(diffReport *diff.Diff, operationsSources *diff.OperationsSourcesMap, config BackwardCompatibilityCheckConfig) []BackwardCompatibilityError { | ||
result := make([]BackwardCompatibilityError, 0) | ||
|
||
result = append(result, checkGlobalSecurity(diffReport, operationsSources, config)...) | ||
|
||
if diffReport.PathsDiff == nil || diffReport.PathsDiff.Modified == nil { | ||
return result | ||
} | ||
|
||
for path, pathItem := range diffReport.PathsDiff.Modified { | ||
if pathItem.OperationsDiff == nil { | ||
continue | ||
} | ||
for operation, operationItem := range pathItem.OperationsDiff.Modified { | ||
|
||
source := (*operationsSources)[operationItem.Revision] | ||
|
||
if operationItem.SecurityDiff == nil { | ||
continue | ||
} | ||
|
||
for _, addedSecurity := range operationItem.SecurityDiff.Added { | ||
if addedSecurity == "" { | ||
continue | ||
} | ||
result = append(result, BackwardCompatibilityError{ | ||
Id: APISecurityAddedCheckId, | ||
Level: INFO, | ||
Text: fmt.Sprintf(config.i18n(APISecurityAddedCheckId), ColorizedValue(addedSecurity)), | ||
Operation: operation, | ||
OperationId: operationItem.Revision.OperationID, | ||
Path: path, | ||
Source: source, | ||
}) | ||
} | ||
|
||
for _, deletedSecurity := range operationItem.SecurityDiff.Deleted { | ||
if deletedSecurity == "" { | ||
continue | ||
} | ||
result = append(result, BackwardCompatibilityError{ | ||
Id: APISecurityRemovedCheckId, | ||
Level: INFO, | ||
Text: fmt.Sprintf(config.i18n(APISecurityRemovedCheckId), ColorizedValue(deletedSecurity)), | ||
Operation: operation, | ||
OperationId: operationItem.Revision.OperationID, | ||
Path: path, | ||
Source: source, | ||
}) | ||
} | ||
|
||
for _, updatedSecurity := range operationItem.SecurityDiff.Modified { | ||
if updatedSecurity.Empty() { | ||
continue | ||
} | ||
for securitySchemeName, updatedSecuritySchemeScopes := range updatedSecurity { | ||
for _, addedScope := range updatedSecuritySchemeScopes.Added { | ||
result = append(result, BackwardCompatibilityError{ | ||
Id: APISecurityScopeAddedId, | ||
Level: INFO, | ||
Text: fmt.Sprintf(config.i18n(APISecurityScopeAddedId), ColorizedValue(addedScope), ColorizedValue(securitySchemeName)), | ||
Operation: operation, | ||
OperationId: operationItem.Revision.OperationID, | ||
Path: path, | ||
Source: source, | ||
}) | ||
} | ||
for _, deletedScope := range updatedSecuritySchemeScopes.Deleted { | ||
result = append(result, BackwardCompatibilityError{ | ||
Id: APISecurityScopeRemovedId, | ||
Level: INFO, | ||
Text: fmt.Sprintf(config.i18n(APISecurityScopeRemovedId), ColorizedValue(deletedScope), ColorizedValue(securitySchemeName)), | ||
Operation: operation, | ||
OperationId: operationItem.Revision.OperationID, | ||
Path: path, | ||
Source: source, | ||
}) | ||
} | ||
} | ||
} | ||
|
||
} | ||
} | ||
|
||
return result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
package checker_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
"github.com/tufin/oasdiff/checker" | ||
"github.com/tufin/oasdiff/diff" | ||
) | ||
|
||
// CL: Adding a new global security to the API | ||
func TestAPIGlobalSecurityyAdded(t *testing.T) { | ||
s1, _ := open("../data/checker/api_security_global_added_base.yaml") | ||
s2, err := open("../data/checker/api_security_global_added_revision.yaml") | ||
require.Empty(t, err) | ||
|
||
d, osm, err := diff.GetWithOperationsSourcesMap(getConfig(), s1, s2) | ||
require.NoError(t, err) | ||
errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.APISecurityUpdatedCheck), d, osm, checker.INFO) | ||
require.NotEmpty(t, errs) | ||
require.Equal(t, checker.BackwardCompatibilityErrors{ | ||
{ | ||
Id: "api-global-security-added", | ||
Text: "the security scheme 'petstore_auth' was added to the API", | ||
Comment: "", | ||
Level: checker.INFO, | ||
Operation: "N/A", | ||
Path: "", | ||
Source: "security.petstore_auth", | ||
OperationId: "N/A", | ||
}}, errs) | ||
} | ||
|
||
// CL: Removing a global security from the API | ||
func TestAPIGlobalSecurityyDeleted(t *testing.T) { | ||
s1, _ := open("../data/checker/api_security_global_added_revision.yaml") | ||
s2, err := open("../data/checker/api_security_global_added_base.yaml") | ||
require.Empty(t, err) | ||
|
||
d, osm, err := diff.GetWithOperationsSourcesMap(getConfig(), s1, s2) | ||
require.NoError(t, err) | ||
errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.APISecurityUpdatedCheck), d, osm, checker.INFO) | ||
require.NotEmpty(t, errs) | ||
require.Equal(t, checker.BackwardCompatibilityErrors{ | ||
{ | ||
Id: "api-global-security-removed", | ||
Text: "the security scheme 'petstore_auth' was removed from the API", | ||
Comment: "", | ||
Level: checker.INFO, | ||
Operation: "N/A", | ||
Path: "", | ||
Source: "security.petstore_auth", | ||
OperationId: "N/A", | ||
}}, errs) | ||
} | ||
|
||
// CL: Removing a security scope from an API global security | ||
func TestAPIGlobalSecurityScopeRemoved(t *testing.T) { | ||
s1, _ := open("../data/checker/api_security_global_added_revision.yaml") | ||
s2, err := open("../data/checker/api_security_global_added_revision.yaml") | ||
require.Empty(t, err) | ||
|
||
s2.Spec.Security[0]["petstore_auth"] = s2.Spec.Security[0]["petstore_auth"][:1] | ||
d, osm, err := diff.GetWithOperationsSourcesMap(getConfig(), s1, s2) | ||
require.NoError(t, err) | ||
errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.APISecurityUpdatedCheck), d, osm, checker.INFO) | ||
require.NotEmpty(t, errs) | ||
require.Equal(t, checker.BackwardCompatibilityErrors{ | ||
{ | ||
Id: "api-global-security-scope-removed", | ||
Text: "the security scope 'read:pets' was removed from the global security scheme 'petstore_auth'", | ||
Comment: "", | ||
Level: checker.INFO, | ||
Operation: "N/A", | ||
Path: "", | ||
Source: "security.scopes.read:pets", | ||
OperationId: "N/A", | ||
}}, errs) | ||
} | ||
|
||
// CL: Adding a security scope from an API global security | ||
func TestAPIGlobalSecurityScopeAdded(t *testing.T) { | ||
s1, _ := open("../data/checker/api_security_global_added_revision.yaml") | ||
s2, err := open("../data/checker/api_security_global_added_revision.yaml") | ||
require.Empty(t, err) | ||
|
||
s1.Spec.Security[0]["petstore_auth"] = s2.Spec.Security[0]["petstore_auth"][:1] | ||
d, osm, err := diff.GetWithOperationsSourcesMap(getConfig(), s1, s2) | ||
require.NoError(t, err) | ||
errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.APISecurityUpdatedCheck), d, osm, checker.INFO) | ||
require.NotEmpty(t, errs) | ||
require.Equal(t, checker.BackwardCompatibilityErrors{ | ||
{ | ||
Id: "api-global-security-scope-added", | ||
Text: "the security scope 'read:pets' was added to the global security scheme 'petstore_auth'", | ||
Comment: "", | ||
Level: checker.INFO, | ||
Operation: "N/A", | ||
Path: "", | ||
Source: "security.scopes.read:pets", | ||
OperationId: "N/A", | ||
}}, errs) | ||
} | ||
|
||
// CL: Adding a new security to the API endpoint | ||
func TestAPISecurityAdded(t *testing.T) { | ||
s1, _ := open("../data/checker/api_security_added_base.yaml") | ||
s2, err := open("../data/checker/api_security_added_revision.yaml") | ||
require.Empty(t, err) | ||
|
||
d, osm, err := diff.GetWithOperationsSourcesMap(getConfig(), s1, s2) | ||
require.NoError(t, err) | ||
errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.APISecurityUpdatedCheck), d, osm, checker.INFO) | ||
require.NotEmpty(t, errs) | ||
require.Equal(t, checker.BackwardCompatibilityErrors{ | ||
{ | ||
Id: "api-security-added", | ||
Text: "the endpoint scheme security 'petstore_auth' was added to the API", | ||
Comment: "", | ||
Level: checker.INFO, | ||
Operation: "POST", | ||
Path: "/subscribe", | ||
Source: "../data/checker/api_security_added_revision.yaml", | ||
OperationId: "", | ||
}}, errs) | ||
} | ||
|
||
// CL: Removing a new security to the API endpoint | ||
func TestAPISecurityDeleted(t *testing.T) { | ||
s1, _ := open("../data/checker/api_security_added_revision.yaml") | ||
s2, err := open("../data/checker/api_security_added_base.yaml") | ||
require.Empty(t, err) | ||
|
||
d, osm, err := diff.GetWithOperationsSourcesMap(getConfig(), s1, s2) | ||
require.NoError(t, err) | ||
errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.APISecurityUpdatedCheck), d, osm, checker.INFO) | ||
require.NotEmpty(t, errs) | ||
require.Equal(t, checker.BackwardCompatibilityErrors{ | ||
{ | ||
Id: "api-security-removed", | ||
Text: "the endpoint scheme security 'petstore_auth' was removed from the API", | ||
Comment: "", | ||
Level: checker.INFO, | ||
Operation: "POST", | ||
Path: "/subscribe", | ||
Source: "../data/checker/api_security_added_base.yaml", | ||
OperationId: "", | ||
}}, errs) | ||
} | ||
|
||
// CL: Removing a security scope from an API endpoint security | ||
func TestAPISecurityScopeRemoved(t *testing.T) { | ||
s1, _ := open("../data/checker/api_security_updated_base.yaml") | ||
s2, err := open("../data/checker/api_security_updated_revision.yaml") | ||
require.Empty(t, err) | ||
|
||
d, osm, err := diff.GetWithOperationsSourcesMap(getConfig(), s1, s2) | ||
require.NoError(t, err) | ||
errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.APISecurityUpdatedCheck), d, osm, checker.INFO) | ||
require.NotEmpty(t, errs) | ||
require.Equal(t, checker.BackwardCompatibilityErrors{ | ||
{ | ||
Id: "api-security-scope-removed", | ||
Text: "the security scope 'read:pets' was removed from the endpoint's security scheme 'petstore_auth'", | ||
Comment: "", | ||
Level: checker.INFO, | ||
Operation: "POST", | ||
Path: "/subscribe", | ||
Source: "../data/checker/api_security_updated_revision.yaml", | ||
OperationId: "", | ||
}}, errs) | ||
} | ||
|
||
// CL: Adding a security scope to an API endpoint security | ||
func TestAPISecurityScopeAdded(t *testing.T) { | ||
s1, _ := open("../data/checker/api_security_updated_revision.yaml") | ||
s2, err := open("../data/checker/api_security_updated_base.yaml") | ||
require.Empty(t, err) | ||
|
||
d, osm, err := diff.GetWithOperationsSourcesMap(getConfig(), s1, s2) | ||
require.NoError(t, err) | ||
errs := checker.CheckBackwardCompatibilityUntilLevel(singleCheckConfig(checker.APISecurityUpdatedCheck), d, osm, checker.INFO) | ||
require.NotEmpty(t, errs) | ||
require.Equal(t, checker.BackwardCompatibilityErrors{ | ||
{ | ||
Id: "api-security-scope-added", | ||
Text: "the security scope 'read:pets' was added to the endpoint's security scheme 'petstore_auth'", | ||
Comment: "", | ||
Level: checker.INFO, | ||
Operation: "POST", | ||
Path: "/subscribe", | ||
Source: "../data/checker/api_security_updated_base.yaml", | ||
OperationId: "", | ||
}}, errs) | ||
} |
Oops, something went wrong.