From 247dd7ae5d3ed112fe01675563fa3ffed5e801b2 Mon Sep 17 00:00:00 2001 From: Rico Chavez-Lopez Date: Wed, 21 Sep 2022 14:41:33 -0700 Subject: [PATCH] fix: added consul policy list check Added a check in getPolicyByName to see whether the policy exists in the policy list before attempting to get the policy. This prevents erroneous or unclear logging. closes: #4108 Signed-off-by: Rico Chavez-Lopez --- .../command/setupacl/aclpolicies.go | 53 ++++++++++++++++++- .../setupacl/stubregistryserver_test.go | 16 ++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/internal/security/bootstrapper/command/setupacl/aclpolicies.go b/internal/security/bootstrapper/command/setupacl/aclpolicies.go index 569a842f62..2b68d3b963 100644 --- a/internal/security/bootstrapper/command/setupacl/aclpolicies.go +++ b/internal/security/bootstrapper/command/setupacl/aclpolicies.go @@ -66,6 +66,7 @@ const ( edgeXServicePolicyName = "edgex-service-policy" consulCreatePolicyAPI = "/v1/acl/policy" + consulPolicyListAPI = "/v1/acl/policies" consulReadPolicyByNameAPI = "/v1/acl/policy/name/%s" aclNotFoundMessage = "ACL not found" @@ -105,6 +106,10 @@ const ( edgeXManagementPolicyName = "edgex-management-policy" ) +type PolicyListResponse []struct { + Name string `json:"Name"` +} + // getOrCreateRegistryPolicy retrieves or creates a new policy // it inserts a new policy if the policy name does not exist and returns a policy // it returns the same policy if the policy name already exists @@ -184,6 +189,53 @@ func (c *cmd) getOrCreateRegistryPolicy(tokenID, policyName, policyRules string) // getPolicyByName gets policy by policy name, returns nil if not found func (c *cmd) getPolicyByName(tokenID, policyName string) (*Policy, error) { + var isExistingPolicy bool + isExistingPolicy = false + + policyListURL, err := c.getRegistryApiUrl(consulPolicyListAPI) + if err != nil { + return nil, err + } + + policyListReq, err := http.NewRequest(http.MethodGet, policyListURL, http.NoBody) + if err != nil { + return nil, fmt.Errorf("Failed to prepare policyListReq request for http URL %s: %w", policyListURL, err) + } + + policyListReq.Header.Add(share.ConsulTokenHeader, tokenID) + policyListResp, err := c.client.Do(policyListReq) + if err != nil { + return nil, fmt.Errorf("Failed to GET policy list request for http URL %s: %w", policyListURL, err) + } + defer policyListResp.Body.Close() + + var policyList PolicyListResponse + + decode_err := json.NewDecoder(policyListResp.Body).Decode(&policyList) + if decode_err != nil { + return nil, fmt.Errorf("Failed to decode policy list reponse: %w", decode_err) + } + + switch policyListResp.StatusCode { + case http.StatusOK: + for _, policy := range policyList { + if policyName == policy.Name { + isExistingPolicy = true + break + } + } + default: + return nil, fmt.Errorf("Failed to get consul policy list from [%s] and status code= %d", consulPolicyListAPI, + policyListResp.StatusCode) + } + + if !isExistingPolicy { + c.loggingClient.Infof("Policy %s does not exist, continuing to create", policyName) + return nil, nil + } + + c.loggingClient.Infof("Policy %s exists, getting policy", policyName) + readPolicyByNameURL, err := c.getRegistryApiUrl(fmt.Sprintf(consulReadPolicyByNameAPI, policyName)) if err != nil { return nil, err @@ -208,7 +260,6 @@ func (c *cmd) getPolicyByName(tokenID, policyName string) (*Policy, error) { if err != nil { return nil, fmt.Errorf("Failed to read readPolicyByName response body: %w", err) } - switch resp.StatusCode { case http.StatusOK: var existing Policy diff --git a/internal/security/bootstrapper/command/setupacl/stubregistryserver_test.go b/internal/security/bootstrapper/command/setupacl/stubregistryserver_test.go index 008dde483a..399217c1ab 100644 --- a/internal/security/bootstrapper/command/setupacl/stubregistryserver_test.go +++ b/internal/security/bootstrapper/command/setupacl/stubregistryserver_test.go @@ -332,6 +332,22 @@ func (registry *registryTestServer) getRegistryServerConf(t *testing.T) *config. w.WriteHeader(http.StatusInternalServerError) _, _ = w.Write([]byte("Invalid Policy: A Policy with Name " + edgeXServicePolicyName + " already exists")) } + case consulPolicyListAPI: + require.Equal(t, http.MethodGet, r.Method) + w.WriteHeader(http.StatusOK) + jsonResponse := []map[string]interface{}{ + { + "Name": "global-management", + }, + { + "Name": "node-read", + }, + { + "Name": "test-policy-name", + }, + } + err := json.NewEncoder(w).Encode(jsonResponse) + require.NoError(t, err) default: t.Fatalf("Unexpected call to URL %s", r.URL.EscapedPath()) }