Skip to content

Commit

Permalink
collection guids matches against staged values, not deployed
Browse files Browse the repository at this point in the history
Using the redact=false on the properties endpoint, we are able to get the values of the credentials.
This allows bypassing the GET credential looking that returned nothing (404).
Only in the case when the tile migrated a property name on a staged product.

[#174733258]

Signed-off-by: Jesse Alford <[email protected]>
  • Loading branch information
jtarchie authored and anEXPer committed Sep 11, 2020
1 parent 7484e9b commit fa31280
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 327 deletions.
45 changes: 31 additions & 14 deletions acceptance/staged_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ var _ = Describe("staged-config command", func() {
ghttp.RespondWith(http.StatusOK, stagedProductsJSON),
),
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/api/v0/staged/products/some-product-guid/properties"),
ghttp.VerifyRequest("GET", "/api/v0/staged/products/some-product-guid/properties", "redact=true"),
ghttp.RespondWith(http.StatusOK, stagedPropertiesJSON),
),
ghttp.CombineHandlers(
Expand Down Expand Up @@ -140,19 +140,8 @@ syslog-properties:
ghttp.RespondWith(http.StatusOK, stagedProductsJSON),
),
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/api/v0/staged/products/some-product-guid/properties"),
ghttp.RespondWith(http.StatusOK, stagedPropertiesJSON),
),
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/api/v0/deployed/products/some-product-guid/credentials/.properties.some-secret-property"),
ghttp.RespondWith(http.StatusOK, `{
"credential": {
"type": "some-secret-type",
"value": {
"some-secret-key": "some-secret-value"
}
}
}`),
ghttp.VerifyRequest("GET", "/api/v0/staged/products/some-product-guid/properties", "redact=false"),
ghttp.RespondWith(http.StatusOK, stagedPropertiesWithSecretsNotRedactedJSON),
),
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/api/v0/staged/products/some-product-guid/networks_and_azs"),
Expand Down Expand Up @@ -247,6 +236,34 @@ const stagedProductsJSON = `[
{"installation_name":"some-product","guid":"some-product-guid","type":"some-product","product_version":"1.0.0"}
]`

const stagedPropertiesWithSecretsNotRedactedJSON = `{
"properties": {
".properties.some-configurable-property": {
"type": "string",
"configurable": true,
"credential": false,
"value": "some-configurable-value",
"optional": true
},
".properties.some-non-configurable-property": {
"type": "string",
"configurable": false,
"credential": false,
"value": "some-non-configurable-value",
"optional": false
},
".properties.some-secret-property": {
"type": "string",
"configurable": true,
"credential": true,
"value": {
"some-secret-key": "some-secret-value"
},
"optional": true
}
}
}`

const stagedPropertiesJSON = `{
"properties": {
".properties.some-configurable-property": {
Expand Down
38 changes: 19 additions & 19 deletions api/staged_products_property_collection_guid_assigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,30 +87,30 @@ func parseResponsePropertyCollection(input associateExistingCollectionGUIDsInput
return nil, fmt.Errorf("parseResponsePropertyCollection: failed to convert %v to []interface{}", input.ExistingProperty.Value)
}

for index, item := range rawItemSlice {
for _, item := range rawItemSlice {
itemMap, ok := item.(map[interface{}]interface{})
if !ok {
return nil, fmt.Errorf("parseResponsePropertyCollection: failed to convert %v to map[interface{}]interface{}", item)
}

for collectionItemKey, collectionItemObj := range itemMap {
collectionItemObjAsMap := collectionItemObj.(map[interface{}]interface{})
isCredential := collectionItemObjAsMap["credential"].(bool)
if !isCredential {
continue
}

credentialName := fmt.Sprintf("%s[%d].%s", input.PropertyName, index, collectionItemKey)
apiOutput, err := input.APIService.GetDeployedProductCredential(GetDeployedProductCredentialInput{
DeployedGUID: input.ProductGUID,
CredentialReference: credentialName,
})
if err != nil {
return nil, err
}

collectionItemObjAsMap["value"] = apiOutput.Credential.Value
}
//for collectionItemKey, collectionItemObj := range itemMap {
// collectionItemObjAsMap := collectionItemObj.(map[interface{}]interface{})
// isCredential := collectionItemObjAsMap["credential"].(bool)
// if !isCredential {
// continue
// }
//
// //credentialName := fmt.Sprintf("%s[%d].%s", input.PropertyName, index, collectionItemKey)
// //apiOutput, err := input.APIService.GetDeployedProductCredential(GetDeployedProductCredentialInput{
// // DeployedGUID: input.ProductGUID,
// // CredentialReference: credentialName,
// //})
// //if err != nil {
// // return nil, err
// //}
//
// collectionItemObjAsMap["value"] = apiOutput.Credential.Value
//}

collection = append(collection, responsePropertyCollectionItem{Data: itemMap})
}
Expand Down
10 changes: 7 additions & 3 deletions api/staged_products_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func (a Api) GetStagedProductSyslogConfiguration(product string) (map[string]int
}

func (a Api) UpdateStagedProductProperties(input UpdateStagedProductPropertiesInput) error {
currentConfiguredProperties, err := a.GetStagedProductProperties(input.GUID)
currentConfiguredProperties, err := a.GetStagedProductProperties(input.GUID, false)
if err != nil {
return err
}
Expand Down Expand Up @@ -311,8 +311,12 @@ func (a Api) GetStagedProductManifest(guid string) (string, error) {
return string(manifest), nil
}

func (a Api) GetStagedProductProperties(product string) (map[string]ResponseProperty, error) {
resp, err := a.fetchProductResource(product, "properties")
func (a Api) GetStagedProductProperties(product string, redact bool) (map[string]ResponseProperty, error) {
endpoint := "properties?redact=false"
if redact {
endpoint = "properties?redact=true"
}
resp, err := a.fetchProductResource(product, endpoint)
if err != nil {
return nil, err
}
Expand Down
106 changes: 36 additions & 70 deletions api/staged_products_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ valid options configurations include percentages ('50%'), counts ('2'), and 'def
BeforeEach(func() {
client.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/api/v0/staged/products/some-product-guid/properties"),
ghttp.VerifyRequest("GET", "/api/v0/staged/products/some-product-guid/properties", "redact=false"),
ghttp.RespondWith(http.StatusOK, `{
"properties": {
"sample": {
Expand Down Expand Up @@ -519,7 +519,7 @@ valid options configurations include percentages ('50%'), counts ('2'), and 'def
"configurable": true,
"credential": true,
"value": {
"secret": "***"
"secret": "unchanged_secret"
},
"optional": false
},
Expand All @@ -529,7 +529,7 @@ valid options configurations include percentages ('50%'), counts ('2'), and 'def
"credential": true,
"value": {
"identity": "unchanged-username",
"password": "***"
"password": "unchanged-password"
},
"optional": true
}
Expand Down Expand Up @@ -712,31 +712,32 @@ valid options configurations include percentages ('50%'), counts ('2'), and 'def
})
Expect(err).ToNot(HaveOccurred())
})

It("adds the guid for elements with secrets that haven't changed and don't have a logical key field", func() {
client.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/api/v0/deployed/products/some-product-guid/credentials/collection_with_secrets[0].super_secret_property"),
ghttp.RespondWith(http.StatusOK, `{
"credential": {
"type": "secret",
"value": {
"secret": "unchanged_secret"
}
}
}`),
),
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/api/v0/deployed/products/some-product-guid/credentials/collection_with_secrets[0].secret_credentials"),
ghttp.RespondWith(http.StatusOK, `{
"credential": {
"type": "simple_credentials",
"value": {
"identity": "unchanged-username",
"password": "unchanged-password"
}
}
}`),
),
//ghttp.CombineHandlers(
// ghttp.VerifyRequest("GET", "/api/v0/deployed/products/some-product-guid/credentials/collection_with_secrets[0].super_secret_property"),
// ghttp.RespondWith(http.StatusOK, `{
// "credential": {
// "type": "secret",
// "value": {
// "secret": "unchanged_secret"
// }
// }
// }`),
//),
//ghttp.CombineHandlers(
// ghttp.VerifyRequest("GET", "/api/v0/deployed/products/some-product-guid/credentials/collection_with_secrets[0].secret_credentials"),
// ghttp.RespondWith(http.StatusOK, `{
// "credential": {
// "type": "simple_credentials",
// "value": {
// "identity": "unchanged-username",
// "password": "unchanged-password"
// }
// }
// }`),
//),
ghttp.CombineHandlers(
ghttp.VerifyRequest("PUT", "/api/v0/staged/products/some-product-guid/properties"),
ghttp.VerifyContentType("application/json"),
Expand Down Expand Up @@ -780,6 +781,7 @@ valid options configurations include percentages ('50%'), counts ('2'), and 'def
})
Expect(err).ToNot(HaveOccurred())
})

It("adds the guid for elements that have a name property", func() {
client.AppendHandlers(
ghttp.CombineHandlers(
Expand Down Expand Up @@ -817,6 +819,7 @@ valid options configurations include percentages ('50%'), counts ('2'), and 'def
})
Expect(err).ToNot(HaveOccurred())
})

It("adds the guid for elements that have a key property", func() {
client.AppendHandlers(
ghttp.CombineHandlers(
Expand Down Expand Up @@ -854,6 +857,7 @@ valid options configurations include percentages ('50%'), counts ('2'), and 'def
})
Expect(err).ToNot(HaveOccurred())
})

It("adds the guid for elements that have logical key property ending in 'name'", func() {
client.AppendHandlers(
ghttp.CombineHandlers(
Expand Down Expand Up @@ -891,6 +895,7 @@ valid options configurations include percentages ('50%'), counts ('2'), and 'def
})
Expect(err).ToNot(HaveOccurred())
})

It("adds the guid using different strategies for different items in the same collection", func() {
client.AppendHandlers(
ghttp.CombineHandlers(
Expand Down Expand Up @@ -935,6 +940,7 @@ valid options configurations include percentages ('50%'), counts ('2'), and 'def
})
Expect(err).ToNot(HaveOccurred())
})

It("no guid added", func() {
client.AppendHandlers(
ghttp.CombineHandlers(
Expand Down Expand Up @@ -1040,46 +1046,6 @@ valid options configurations include percentages ('50%'), counts ('2'), and 'def
})

Describe("GetStagedProductSyslogConfiguration", func() {
//BeforeEach(func() {
// client.DoStub = func(req *http.Request) (*http.Response, error) {
// var resp *http.Response
// if strings.Contains(req.URL.Path, "some-product-guid") {
// resp = &http.Response{
// StatusCode: http.StatusOK,
// Body: ioutil.NopCloser(bytes.NewBufferString(`{
// "syslog_configuration": {
// "enabled": true,
// "address": "example.com"
// }
// }`)),
// }
// } else if strings.Contains(req.URL.Path, "missing-syslog-config") {
// resp = &http.Response{
// StatusCode: http.StatusUnprocessableEntity,
// Body: ioutil.NopCloser(bytes.NewBufferString(`{
// "errors": {
// "syslog": ["This product does not support the Ops Manager consistent syslog configuration feature. If the product supports custom syslog configuration, those properties can be set via the /api/v0/staged/products/:product_guid/properties endpoint."]
// }
// }`)),
// }
// } else if strings.Contains(req.URL.Path, "bad-response-code") {
// resp = &http.Response{
// StatusCode: http.StatusBadRequest,
// Body: ioutil.NopCloser(bytes.NewBufferString("")),
// }
// } else {
// resp = &http.Response{
// StatusCode: http.StatusOK,
// Body: ioutil.NopCloser(bytes.NewBufferString(`{
// invalid-json
// }`)),
// }
// }
//
// return resp, nil
// }
//})

When("syslog configuration is configured for the specified product", func() {
It("returns the syslog configuration ", func() {
client.AppendHandlers(
Expand Down Expand Up @@ -1326,7 +1292,7 @@ key-4: 2147483648
),
)

config, err := service.GetStagedProductProperties("some-product-guid")
config, err := service.GetStagedProductProperties("some-product-guid", true)
Expect(err).ToNot(HaveOccurred())

Expect(config).To(HaveKeyWithValue(".properties.some-configurable-property", api.ResponseProperty{
Expand Down Expand Up @@ -1363,7 +1329,7 @@ key-4: 2147483648
It("returns an error", func() {
client.Close()

_, err := service.GetStagedProductProperties("some-product-guid")
_, err := service.GetStagedProductProperties("some-product-guid", true)
Expect(err).To(MatchError(ContainSubstring(`could not make api request to staged product properties endpoint: could not send api request to GET /api/v0/staged/products/some-product-guid/properties`)))
})
})
Expand All @@ -1377,7 +1343,7 @@ key-4: 2147483648
),
)

_, err := service.GetStagedProductProperties("some-product-guid")
_, err := service.GetStagedProductProperties("some-product-guid", true)
Expect(err).To(MatchError(ContainSubstring("request failed: unexpected response")))
})
})
Expand All @@ -1391,7 +1357,7 @@ key-4: 2147483648
),
)

_, err := service.GetStagedProductProperties("some-product-guid")
_, err := service.GetStagedProductProperties("some-product-guid", true)
Expect(err).To(MatchError(ContainSubstring("could not parse json")))
})
})
Expand Down
Loading

0 comments on commit fa31280

Please sign in to comment.