{"record":{"id":"6b709c8da98a8c2b","repo":"grpc/grpc-go","slug":"allow-rules-is-not-present","errorCode":null,"errorMessage":"\"allow_rules\" is not present","messagePattern":"\"allow_rules\" is not present","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"authz/rbac_translator.go","lineNumber":373,"sourceCode":"\t}\n}\n\n// translatePolicy translates SDK authorization policy in JSON format to two\n// Envoy RBAC polices (deny followed by allow policy) or only one Envoy RBAC\n// allow policy. Also returns the overall policy name. If the input policy\n// cannot be parsed or is invalid, an error will be returned.\nfunc translatePolicy(policyStr string) ([]*v3rbacpb.RBAC, string, error) {\n\tpolicy := &authorizationPolicy{}\n\td := json.NewDecoder(bytes.NewReader([]byte(policyStr)))\n\td.DisallowUnknownFields()\n\tif err := d.Decode(policy); err != nil {\n\t\treturn nil, \"\", fmt.Errorf(\"failed to unmarshal policy: %v\", err)\n\t}\n\tif policy.Name == \"\" {\n\t\treturn nil, \"\", fmt.Errorf(`\"name\" is not present`)\n\t}\n\tif len(policy.AllowRules) == 0 {\n\t\treturn nil, \"\", fmt.Errorf(`\"allow_rules\" is not present`)\n\t}\n\tallowLogger, denyLogger, err := policy.AuditLoggingOptions.toProtos()\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\trbacs := make([]*v3rbacpb.RBAC, 0, 2)\n\tif len(policy.DenyRules) > 0 {\n\t\tdenyPolicies, err := parseRules(policy.DenyRules, policy.Name)\n\t\tif err != nil {\n\t\t\treturn nil, \"\", fmt.Errorf(`\"deny_rules\" %v`, err)\n\t\t}\n\t\tdenyRBAC := &v3rbacpb.RBAC{\n\t\t\tAction:              v3rbacpb.RBAC_DENY,\n\t\t\tPolicies:            denyPolicies,\n\t\t\tAuditLoggingOptions: denyLogger,\n\t\t}\n\t\trbacs = append(rbacs, denyRBAC)\n\t}","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/authz/rbac_translator.go#L355-L391","documentation":"Returned by translatePolicy (rbac_translator.go:373) when the policy has a name but len(AllowRules) == 0. allow_rules is mandatory because the SDK policy is an allow-list (default-deny); with no allow rules, no request could ever be authorized, which is treated as a misconfiguration rather than a valid deny-all policy.","triggerScenarios":"Policy JSON with a name and possibly deny_rules, but no allow_rules array (or an empty one).","commonSituations":"Authoring a deny-first policy and forgetting the allow list; truncation during templating; intending deny-all but the SDK requires an explicit allow rule.","solutions":["Add at least one allow rule (e.g. an allow-all baseline {\"name\":\"allow_all\",\"request\":{\"paths\":[\"/\"]}}) and rely on deny_rules to restrict.","Re-read the policy model: allow_rules is required; deny_rules is optional."],"exampleFix":"// before\n{ \"name\": \"p\", \"deny_rules\": [ {\"name\":\"block\",\"request\":{\"paths\":[\"/admin\"]}} ] }\n\n// after\n{\n  \"name\": \"p\",\n  \"allow_rules\": [ {\"name\":\"base\",\"request\":{\"paths\":[\"/\"]}} ],\n  \"deny_rules\": [ {\"name\":\"block\",\"request\":{\"paths\":[\"/admin\"]}} ]\n}","handlingStrategy":"validation","validationCode":"if len(allowRules) == 0 {\n    return errors.New(\"at least one allow_rule is required\")\n}","typeGuard":null,"tryCatchPattern":"interceptor, err := authz.NewStatic(policyJSON)\nif err != nil {\n    if err.Error() == `\"allow_rules\" is not present` {\n        // add at least one allow rule and reload\n    }\n}","preventionTips":["Remember the SDK policy is allow-list based; allow_rules is mandatory.","Add an allow-all baseline rule and use deny_rules to restrict."],"tags":["grpc","authz","rbac","policy","config","go"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}