mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 10:37:56 +00:00 
			
		
		
		
	backport of commit d08bf5616d (#19347)
				
					
				
			Co-authored-by: Steven Clark <steven.clark@hashicorp.com>
This commit is contained in:
		 hc-github-team-secure-vault-core
					hc-github-team-secure-vault-core
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							8545876076
						
					
				
				
					commit
					c496011eed
				
			| @@ -119,6 +119,10 @@ func (e *Executor) Execute() (map[string][]*Result, error) { | ||||
| 			return nil, fmt.Errorf("failed to evaluate %v: %w", checker.Name(), err) | ||||
| 		} | ||||
|  | ||||
| 		if results == nil { | ||||
| 			results = []*Result{} | ||||
| 		} | ||||
|  | ||||
| 		for _, result := range results { | ||||
| 			result.Endpoint = e.templatePath(result.Endpoint) | ||||
| 			result.StatusDisplay = ResultStatusNameMap[result.Status] | ||||
|   | ||||
| @@ -13,12 +13,14 @@ type HardwareBackedRoot struct { | ||||
|  | ||||
| 	UnsupportedVersion bool | ||||
|  | ||||
| 	FetchIssues  map[string]*PathFetch | ||||
| 	IssuerKeyMap map[string]string | ||||
| 	KeyIsManaged map[string]string | ||||
| } | ||||
|  | ||||
| func NewHardwareBackedRootCheck() Check { | ||||
| 	return &HardwareBackedRoot{ | ||||
| 		FetchIssues:  make(map[string]*PathFetch), | ||||
| 		IssuerKeyMap: make(map[string]string), | ||||
| 		KeyIsManaged: make(map[string]string), | ||||
| 	} | ||||
| @@ -64,6 +66,7 @@ func (h *HardwareBackedRoot) FetchResources(e *Executor) error { | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			h.FetchIssues[issuer] = ret | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| @@ -83,13 +86,15 @@ func (h *HardwareBackedRoot) FetchResources(e *Executor) error { | ||||
| 		} | ||||
|  | ||||
| 		h.IssuerKeyMap[issuer] = keyId | ||||
| 		skip, _, keyEntry, err := pkiFetchKeyEntry(e, keyId, func() { | ||||
| 		skip, ret, keyEntry, err := pkiFetchKeyEntry(e, keyId, func() { | ||||
| 			h.UnsupportedVersion = true | ||||
| 		}) | ||||
| 		if skip || err != nil || keyEntry == nil { | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| 			h.FetchIssues[issuer] = ret | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| @@ -112,6 +117,25 @@ func (h *HardwareBackedRoot) Evaluate(e *Executor) (results []*Result, err error | ||||
| 		return []*Result{&ret}, nil | ||||
| 	} | ||||
|  | ||||
| 	for issuer, fetchPath := range h.FetchIssues { | ||||
| 		if fetchPath != nil && fetchPath.IsSecretPermissionsError() { | ||||
| 			delete(h.IssuerKeyMap, issuer) | ||||
| 			ret := Result{ | ||||
| 				Status:   ResultInsufficientPermissions, | ||||
| 				Endpoint: fetchPath.Path, | ||||
| 				Message:  "Without this information, this health check is unable to function.", | ||||
| 			} | ||||
|  | ||||
| 			if e.Client.Token() == "" { | ||||
| 				ret.Message = "No token available so unable for the endpoint for this mount. " + ret.Message | ||||
| 			} else { | ||||
| 				ret.Message = "This token lacks permission for the endpoint for this mount. " + ret.Message | ||||
| 			} | ||||
|  | ||||
| 			results = append(results, &ret) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for name, keyId := range h.IssuerKeyMap { | ||||
| 		var ret Result | ||||
| 		ret.Status = ResultInformational | ||||
|   | ||||
| @@ -10,13 +10,15 @@ import ( | ||||
| type RoleAllowsGlobWildcards struct { | ||||
| 	Enabled            bool | ||||
| 	UnsupportedVersion bool | ||||
| 	NoPerms            bool | ||||
|  | ||||
| 	RoleListFetchIssue *PathFetch | ||||
| 	RoleFetchIssues    map[string]*PathFetch | ||||
| 	RoleEntryMap       map[string]map[string]interface{} | ||||
| } | ||||
|  | ||||
| func NewRoleAllowsGlobWildcardsCheck() Check { | ||||
| 	return &RoleAllowsGlobWildcards{ | ||||
| 		RoleFetchIssues: make(map[string]*PathFetch), | ||||
| 		RoleEntryMap:    make(map[string]map[string]interface{}), | ||||
| 	} | ||||
| } | ||||
| @@ -49,7 +51,7 @@ func (h *RoleAllowsGlobWildcards) FetchResources(e *Executor) error { | ||||
| 	}) | ||||
| 	if exit || err != nil { | ||||
| 		if f != nil && f.IsSecretPermissionsError() { | ||||
| 			h.NoPerms = true | ||||
| 			h.RoleListFetchIssue = f | ||||
| 		} | ||||
| 		return err | ||||
| 	} | ||||
| @@ -60,7 +62,7 @@ func (h *RoleAllowsGlobWildcards) FetchResources(e *Executor) error { | ||||
| 		}) | ||||
| 		if skip || err != nil || entry == nil { | ||||
| 			if f != nil && f.IsSecretPermissionsError() { | ||||
| 				h.NoPerms = true | ||||
| 				h.RoleFetchIssues[role] = f | ||||
| 			} | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| @@ -84,19 +86,38 @@ func (h *RoleAllowsGlobWildcards) Evaluate(e *Executor) (results []*Result, err | ||||
| 		} | ||||
| 		return []*Result{&ret}, nil | ||||
| 	} | ||||
| 	if h.NoPerms { | ||||
| 	if h.RoleListFetchIssue != nil && h.RoleListFetchIssue.IsSecretPermissionsError() { | ||||
| 		ret := Result{ | ||||
| 			Status:   ResultInsufficientPermissions, | ||||
| 			Endpoint: "/{{mount}}/roles", | ||||
| 			Message:  "lacks permission either to list the roles or to read a specific role. This may restrict the ability to fully execute this health check.", | ||||
| 			Endpoint: h.RoleListFetchIssue.Path, | ||||
| 			Message:  "lacks permission either to list the roles. This restricts the ability to fully execute this health check.", | ||||
| 		} | ||||
| 		if e.Client.Token() == "" { | ||||
| 			ret.Message = "No token available and so this health check " + ret.Message | ||||
| 		} else { | ||||
| 			ret.Message = "This token " + ret.Message | ||||
| 		} | ||||
| 		return []*Result{&ret}, nil | ||||
| 	} | ||||
|  | ||||
| 	for role, fetchPath := range h.RoleFetchIssues { | ||||
| 		if fetchPath != nil && fetchPath.IsSecretPermissionsError() { | ||||
| 			delete(h.RoleEntryMap, role) | ||||
| 			ret := Result{ | ||||
| 				Status:   ResultInsufficientPermissions, | ||||
| 				Endpoint: fetchPath.Path, | ||||
| 				Message:  "Without this information, this health check is unable to function.", | ||||
| 			} | ||||
|  | ||||
| 			if e.Client.Token() == "" { | ||||
| 				ret.Message = "No token available so unable for the endpoint for this mount. " + ret.Message | ||||
| 			} else { | ||||
| 				ret.Message = "This token lacks permission the endpoint for this mount. " + ret.Message | ||||
| 			} | ||||
|  | ||||
| 			results = append(results, &ret) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for role, entry := range h.RoleEntryMap { | ||||
| 		allowsWildcards, present := entry["allow_wildcard_certificates"] | ||||
|   | ||||
| @@ -9,13 +9,15 @@ import ( | ||||
| type RoleAllowsLocalhost struct { | ||||
| 	Enabled            bool | ||||
| 	UnsupportedVersion bool | ||||
| 	NoPerms            bool | ||||
|  | ||||
| 	RoleListFetchIssue *PathFetch | ||||
| 	RoleFetchIssues    map[string]*PathFetch | ||||
| 	RoleEntryMap       map[string]map[string]interface{} | ||||
| } | ||||
|  | ||||
| func NewRoleAllowsLocalhostCheck() Check { | ||||
| 	return &RoleAllowsLocalhost{ | ||||
| 		RoleFetchIssues: make(map[string]*PathFetch), | ||||
| 		RoleEntryMap:    make(map[string]map[string]interface{}), | ||||
| 	} | ||||
| } | ||||
| @@ -48,7 +50,7 @@ func (h *RoleAllowsLocalhost) FetchResources(e *Executor) error { | ||||
| 	}) | ||||
| 	if exit || err != nil { | ||||
| 		if f != nil && f.IsSecretPermissionsError() { | ||||
| 			h.NoPerms = true | ||||
| 			h.RoleListFetchIssue = f | ||||
| 		} | ||||
| 		return err | ||||
| 	} | ||||
| @@ -59,7 +61,7 @@ func (h *RoleAllowsLocalhost) FetchResources(e *Executor) error { | ||||
| 		}) | ||||
| 		if skip || err != nil || entry == nil { | ||||
| 			if f != nil && f.IsSecretPermissionsError() { | ||||
| 				h.NoPerms = true | ||||
| 				h.RoleFetchIssues[role] = f | ||||
| 			} | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| @@ -83,19 +85,39 @@ func (h *RoleAllowsLocalhost) Evaluate(e *Executor) (results []*Result, err erro | ||||
| 		} | ||||
| 		return []*Result{&ret}, nil | ||||
| 	} | ||||
| 	if h.NoPerms { | ||||
|  | ||||
| 	if h.RoleListFetchIssue != nil && h.RoleListFetchIssue.IsSecretPermissionsError() { | ||||
| 		ret := Result{ | ||||
| 			Status:   ResultInsufficientPermissions, | ||||
| 			Endpoint: "/{{mount}}/roles", | ||||
| 			Message:  "lacks permission either to list the roles or to read a specific role. This may restrict the ability to fully execute this health check", | ||||
| 			Endpoint: h.RoleListFetchIssue.Path, | ||||
| 			Message:  "lacks permission either to list the roles. This restricts the ability to fully execute this health check.", | ||||
| 		} | ||||
| 		if e.Client.Token() == "" { | ||||
| 			ret.Message = "No token available and so this health check " + ret.Message | ||||
| 		} else { | ||||
| 			ret.Message = "This token " + ret.Message | ||||
| 		} | ||||
| 		return []*Result{&ret}, nil | ||||
| 	} | ||||
|  | ||||
| 	for role, fetchPath := range h.RoleFetchIssues { | ||||
| 		if fetchPath != nil && fetchPath.IsSecretPermissionsError() { | ||||
| 			delete(h.RoleEntryMap, role) | ||||
| 			ret := Result{ | ||||
| 				Status:   ResultInsufficientPermissions, | ||||
| 				Endpoint: fetchPath.Path, | ||||
| 				Message:  "Without this information, this health check is unable to function.", | ||||
| 			} | ||||
|  | ||||
| 			if e.Client.Token() == "" { | ||||
| 				ret.Message = "No token available so unable for the endpoint for this mount. " + ret.Message | ||||
| 			} else { | ||||
| 				ret.Message = "This token lacks permission the endpoint for this mount. " + ret.Message | ||||
| 			} | ||||
|  | ||||
| 			results = append(results, &ret) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for role, entry := range h.RoleEntryMap { | ||||
| 		allowsLocalhost := entry["allow_localhost"].(bool) | ||||
|   | ||||
| @@ -11,17 +11,18 @@ import ( | ||||
| type RoleNoStoreFalse struct { | ||||
| 	Enabled            bool | ||||
| 	UnsupportedVersion bool | ||||
| 	NoPerms            bool | ||||
|  | ||||
| 	AllowedRoles map[string]bool | ||||
|  | ||||
| 	CertCounts   int | ||||
| 	RoleListFetchIssue *PathFetch | ||||
| 	RoleFetchIssues    map[string]*PathFetch | ||||
| 	RoleEntryMap       map[string]map[string]interface{} | ||||
| 	CRLConfig          *PathFetch | ||||
| } | ||||
|  | ||||
| func NewRoleNoStoreFalseCheck() Check { | ||||
| 	return &RoleNoStoreFalse{ | ||||
| 		RoleFetchIssues: make(map[string]*PathFetch), | ||||
| 		AllowedRoles:    make(map[string]bool), | ||||
| 		RoleEntryMap:    make(map[string]map[string]interface{}), | ||||
| 	} | ||||
| @@ -64,7 +65,7 @@ func (h *RoleNoStoreFalse) FetchResources(e *Executor) error { | ||||
| 	}) | ||||
| 	if exit || err != nil { | ||||
| 		if f != nil && f.IsSecretPermissionsError() { | ||||
| 			h.NoPerms = true | ||||
| 			h.RoleListFetchIssue = f | ||||
| 		} | ||||
| 		return err | ||||
| 	} | ||||
| @@ -75,7 +76,7 @@ func (h *RoleNoStoreFalse) FetchResources(e *Executor) error { | ||||
| 		}) | ||||
| 		if skip || err != nil || entry == nil { | ||||
| 			if f != nil && f.IsSecretPermissionsError() { | ||||
| 				h.NoPerms = true | ||||
| 				h.RoleFetchIssues[role] = f | ||||
| 			} | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| @@ -86,14 +87,6 @@ func (h *RoleNoStoreFalse) FetchResources(e *Executor) error { | ||||
| 		h.RoleEntryMap[role] = entry | ||||
| 	} | ||||
|  | ||||
| 	exit, _, leaves, err := pkiFetchLeavesList(e, func() { | ||||
| 		h.UnsupportedVersion = true | ||||
| 	}) | ||||
| 	if exit || err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	h.CertCounts = len(leaves) | ||||
|  | ||||
| 	// Check if the issuer is fetched yet. | ||||
| 	configRet, err := e.FetchIfNotFetched(logical.ReadOperation, "/{{mount}}/config/crl") | ||||
| 	if err != nil { | ||||
| @@ -116,19 +109,38 @@ func (h *RoleNoStoreFalse) Evaluate(e *Executor) (results []*Result, err error) | ||||
| 		return []*Result{&ret}, nil | ||||
| 	} | ||||
|  | ||||
| 	if h.NoPerms { | ||||
| 	if h.RoleListFetchIssue != nil && h.RoleListFetchIssue.IsSecretPermissionsError() { | ||||
| 		ret := Result{ | ||||
| 			Status:   ResultInsufficientPermissions, | ||||
| 			Endpoint: "/{{mount}}/roles", | ||||
| 			Message:  "lacks permission either to list the roles or to read a specific role. This may restrict the ability to fully execute this health check", | ||||
| 			Endpoint: h.RoleListFetchIssue.Path, | ||||
| 			Message:  "lacks permission either to list the roles. This restricts the ability to fully execute this health check.", | ||||
| 		} | ||||
| 		if e.Client.Token() == "" { | ||||
| 			ret.Message = "No token available and so this health check " + ret.Message | ||||
| 		} else { | ||||
| 			ret.Message = "This token " + ret.Message | ||||
| 		} | ||||
| 		return []*Result{&ret}, nil | ||||
| 	} | ||||
|  | ||||
| 	for role, fetchPath := range h.RoleFetchIssues { | ||||
| 		if fetchPath != nil && fetchPath.IsSecretPermissionsError() { | ||||
| 			delete(h.RoleEntryMap, role) | ||||
| 			ret := Result{ | ||||
| 				Status:   ResultInsufficientPermissions, | ||||
| 				Endpoint: fetchPath.Path, | ||||
| 				Message:  "Without this information, this health check is unable to function.", | ||||
| 			} | ||||
|  | ||||
| 			if e.Client.Token() == "" { | ||||
| 				ret.Message = "No token available so unable for the endpoint for this mount. " + ret.Message | ||||
| 			} else { | ||||
| 				ret.Message = "This token lacks permission the endpoint for this mount. " + ret.Message | ||||
| 			} | ||||
|  | ||||
| 			results = append(results, &ret) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	crlAutoRebuild := false | ||||
| 	if h.CRLConfig != nil { | ||||
|   | ||||
| @@ -14,12 +14,14 @@ type RootIssuedLeaves struct { | ||||
|  | ||||
| 	CertsToFetch int | ||||
|  | ||||
| 	FetchIssues map[string]*PathFetch | ||||
| 	RootCertMap map[string]*x509.Certificate | ||||
| 	LeafCertMap map[string]*x509.Certificate | ||||
| } | ||||
|  | ||||
| func NewRootIssuedLeavesCheck() Check { | ||||
| 	return &RootIssuedLeaves{ | ||||
| 		FetchIssues: make(map[string]*PathFetch), | ||||
| 		RootCertMap: make(map[string]*x509.Certificate), | ||||
| 		LeafCertMap: make(map[string]*x509.Certificate), | ||||
| 	} | ||||
| @@ -64,9 +66,10 @@ func (h *RootIssuedLeaves) FetchResources(e *Executor) error { | ||||
| 	} | ||||
|  | ||||
| 	for _, issuer := range issuers { | ||||
| 		skip, _, cert, err := pkiFetchIssuer(e, issuer, func() { | ||||
| 		skip, pathFetch, cert, err := pkiFetchIssuer(e, issuer, func() { | ||||
| 			h.UnsupportedVersion = true | ||||
| 		}) | ||||
| 		h.FetchIssues[issuer] = pathFetch | ||||
| 		if skip || err != nil { | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| @@ -85,10 +88,15 @@ func (h *RootIssuedLeaves) FetchResources(e *Executor) error { | ||||
| 		h.RootCertMap[issuer] = cert | ||||
| 	} | ||||
|  | ||||
| 	exit, _, leaves, err := pkiFetchLeavesList(e, func() { | ||||
| 	exit, f, leaves, err := pkiFetchLeavesList(e, func() { | ||||
| 		h.UnsupportedVersion = true | ||||
| 	}) | ||||
| 	if exit || err != nil { | ||||
| 		if f != nil && f.IsSecretPermissionsError() { | ||||
| 			for _, issuer := range issuers { | ||||
| 				h.FetchIssues[issuer] = f | ||||
| 			} | ||||
| 		} | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| @@ -130,6 +138,25 @@ func (h *RootIssuedLeaves) Evaluate(e *Executor) (results []*Result, err error) | ||||
| 		return []*Result{&ret}, nil | ||||
| 	} | ||||
|  | ||||
| 	for issuer, fetchPath := range h.FetchIssues { | ||||
| 		if fetchPath != nil && fetchPath.IsSecretPermissionsError() { | ||||
| 			delete(h.RootCertMap, issuer) | ||||
| 			ret := Result{ | ||||
| 				Status:   ResultInsufficientPermissions, | ||||
| 				Endpoint: fetchPath.Path, | ||||
| 				Message:  "Without this information, this health check is unable to function.", | ||||
| 			} | ||||
|  | ||||
| 			if e.Client.Token() == "" { | ||||
| 				ret.Message = "No token available so unable for the endpoint for this mount. " + ret.Message | ||||
| 			} else { | ||||
| 				ret.Message = "This token lacks permission for the endpoint for this mount. " + ret.Message | ||||
| 			} | ||||
|  | ||||
| 			results = append(results, &ret) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	issuerHasLeaf := make(map[string]bool) | ||||
| 	for serial, leaf := range h.LeafCertMap { | ||||
| 		if len(issuerHasLeaf) == len(h.RootCertMap) { | ||||
|   | ||||
| @@ -14,6 +14,7 @@ type TooManyCerts struct { | ||||
| 	CountWarning  int | ||||
|  | ||||
| 	CertCounts int | ||||
| 	FetchIssue *PathFetch | ||||
| } | ||||
|  | ||||
| func NewTooManyCertsCheck() Check { | ||||
| @@ -60,7 +61,9 @@ func (h *TooManyCerts) FetchResources(e *Executor) error { | ||||
| 	exit, leavesRet, _, err := pkiFetchLeavesList(e, func() { | ||||
| 		h.UnsupportedVersion = true | ||||
| 	}) | ||||
| 	if exit { | ||||
| 	h.FetchIssue = leavesRet | ||||
|  | ||||
| 	if exit || err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| @@ -80,6 +83,23 @@ func (h *TooManyCerts) Evaluate(e *Executor) (results []*Result, err error) { | ||||
| 		return []*Result{&ret}, nil | ||||
| 	} | ||||
|  | ||||
| 	if h.FetchIssue != nil && h.FetchIssue.IsSecretPermissionsError() { | ||||
| 		ret := Result{ | ||||
| 			Status:   ResultInsufficientPermissions, | ||||
| 			Endpoint: h.FetchIssue.Path, | ||||
| 			Message:  "Without this information, this health check is unable to function.", | ||||
| 		} | ||||
|  | ||||
| 		if e.Client.Token() == "" { | ||||
| 			ret.Message = "No token available so unable to list the endpoint for this mount. " + ret.Message | ||||
| 		} else { | ||||
| 			ret.Message = "This token lacks permission to list the endpoint for this mount. " + ret.Message | ||||
| 		} | ||||
|  | ||||
| 		results = append(results, &ret) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	ret := Result{ | ||||
| 		Status:   ResultOK, | ||||
| 		Endpoint: "/{{mount}}/certs", | ||||
|   | ||||
| @@ -223,7 +223,15 @@ func (c *PKIHealthCheckCommand) Run(args []string) int { | ||||
|  | ||||
| 	// Handle listing, if necessary. | ||||
| 	if c.flagList { | ||||
| 		uiFormat := Format(c.UI) | ||||
| 		if uiFormat == "yaml" { | ||||
| 			c.UI.Error("YAML output format is not supported by the --list command") | ||||
| 			return pkiRetUsage | ||||
| 		} | ||||
|  | ||||
| 		if uiFormat != "json" { | ||||
| 			c.UI.Output("Default health check config:") | ||||
| 		} | ||||
| 		config := map[string]map[string]interface{}{} | ||||
| 		for _, checker := range executor.Checkers { | ||||
| 			config[checker.Name()] = checker.DefaultConfig() | ||||
|   | ||||
| @@ -271,6 +271,8 @@ func testPKIHealthCheckCommand(tb testing.TB) (*cli.MockUi, *PKIHealthCheckComma | ||||
| } | ||||
|  | ||||
| func execPKIHC(t *testing.T, client *api.Client, ok bool) (int, string, map[string][]map[string]interface{}) { | ||||
| 	t.Helper() | ||||
|  | ||||
| 	stdout := bytes.NewBuffer(nil) | ||||
| 	stderr := bytes.NewBuffer(nil) | ||||
| 	runOpts := &RunOptions{ | ||||
| @@ -295,6 +297,8 @@ func execPKIHC(t *testing.T, client *api.Client, ok bool) (int, string, map[stri | ||||
| } | ||||
|  | ||||
| func validateExpectedPKIHC(t *testing.T, expected, results map[string][]map[string]interface{}) { | ||||
| 	t.Helper() | ||||
|  | ||||
| 	for test, subtest := range expected { | ||||
| 		actual, ok := results[test] | ||||
| 		require.True(t, ok, fmt.Sprintf("expected top-level test %v to be present", test)) | ||||
| @@ -615,7 +619,7 @@ var expectedNoPerm = map[string][]map[string]interface{}{ | ||||
| 	}, | ||||
| 	"root_issued_leaves": { | ||||
| 		{ | ||||
| 			"status": "ok", | ||||
| 			"status": "insufficient_permissions", | ||||
| 		}, | ||||
| 	}, | ||||
| 	"tidy_last_run": { | ||||
| @@ -625,7 +629,7 @@ var expectedNoPerm = map[string][]map[string]interface{}{ | ||||
| 	}, | ||||
| 	"too_many_certs": { | ||||
| 		{ | ||||
| 			"status": "ok", | ||||
| 			"status": "insufficient_permissions", | ||||
| 		}, | ||||
| 	}, | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user