rbac_translator_test.go 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052
  1. /*
  2. *
  3. * Copyright 2021 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package authz
  19. import (
  20. "strings"
  21. "testing"
  22. v1xdsudpatypepb "github.com/cncf/xds/go/udpa/type/v1"
  23. "github.com/google/go-cmp/cmp"
  24. "google.golang.org/protobuf/testing/protocmp"
  25. "google.golang.org/protobuf/types/known/anypb"
  26. "google.golang.org/protobuf/types/known/structpb"
  27. v3corepb "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
  28. v3rbacpb "github.com/envoyproxy/go-control-plane/envoy/config/rbac/v3"
  29. v3routepb "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
  30. v3matcherpb "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3"
  31. )
  32. func TestTranslatePolicy(t *testing.T) {
  33. tests := map[string]struct {
  34. authzPolicy string
  35. wantErr string
  36. wantPolicies []*v3rbacpb.RBAC
  37. wantPolicyName string
  38. }{
  39. "valid policy": {
  40. authzPolicy: `{
  41. "name": "authz",
  42. "deny_rules": [
  43. {
  44. "name": "deny_policy_1",
  45. "source": {
  46. "principals":[
  47. "spiffe://foo.abc",
  48. "spiffe://bar*",
  49. "*baz",
  50. "spiffe://abc.*.com"
  51. ]
  52. }
  53. }],
  54. "allow_rules": [
  55. {
  56. "name": "allow_policy_1",
  57. "source": {
  58. "principals":["*"]
  59. },
  60. "request": {
  61. "paths": ["path-foo*"]
  62. }
  63. },
  64. {
  65. "name": "allow_policy_2",
  66. "request": {
  67. "paths": [
  68. "path-bar",
  69. "*baz"
  70. ],
  71. "headers": [
  72. {
  73. "key": "key-1",
  74. "values": ["foo", "*bar"]
  75. },
  76. {
  77. "key": "key-2",
  78. "values": ["baz*"]
  79. }
  80. ]
  81. }
  82. }]
  83. }`,
  84. wantPolicies: []*v3rbacpb.RBAC{
  85. {
  86. Action: v3rbacpb.RBAC_DENY,
  87. Policies: map[string]*v3rbacpb.Policy{
  88. "authz_deny_policy_1": {
  89. Principals: []*v3rbacpb.Principal{
  90. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  91. Ids: []*v3rbacpb.Principal{
  92. {Identifier: &v3rbacpb.Principal_Authenticated_{
  93. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  94. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://foo.abc"},
  95. }},
  96. }},
  97. {Identifier: &v3rbacpb.Principal_Authenticated_{
  98. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  99. MatchPattern: &v3matcherpb.StringMatcher_Prefix{Prefix: "spiffe://bar"},
  100. }},
  101. }},
  102. {Identifier: &v3rbacpb.Principal_Authenticated_{
  103. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  104. MatchPattern: &v3matcherpb.StringMatcher_Suffix{Suffix: "baz"},
  105. }},
  106. }},
  107. {Identifier: &v3rbacpb.Principal_Authenticated_{
  108. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  109. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://abc.*.com"},
  110. }},
  111. }},
  112. },
  113. }}},
  114. },
  115. Permissions: []*v3rbacpb.Permission{
  116. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  117. },
  118. },
  119. },
  120. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{},
  121. },
  122. {
  123. Action: v3rbacpb.RBAC_ALLOW,
  124. Policies: map[string]*v3rbacpb.Policy{
  125. "authz_allow_policy_1": {
  126. Principals: []*v3rbacpb.Principal{
  127. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  128. Ids: []*v3rbacpb.Principal{
  129. {Identifier: &v3rbacpb.Principal_Authenticated_{
  130. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  131. MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}},
  132. }},
  133. }},
  134. },
  135. }}},
  136. },
  137. Permissions: []*v3rbacpb.Permission{
  138. {Rule: &v3rbacpb.Permission_AndRules{AndRules: &v3rbacpb.Permission_Set{
  139. Rules: []*v3rbacpb.Permission{
  140. {Rule: &v3rbacpb.Permission_OrRules{OrRules: &v3rbacpb.Permission_Set{
  141. Rules: []*v3rbacpb.Permission{
  142. {Rule: &v3rbacpb.Permission_UrlPath{
  143. UrlPath: &v3matcherpb.PathMatcher{Rule: &v3matcherpb.PathMatcher_Path{Path: &v3matcherpb.StringMatcher{
  144. MatchPattern: &v3matcherpb.StringMatcher_Prefix{Prefix: "path-foo"},
  145. }}},
  146. }},
  147. },
  148. }}},
  149. },
  150. }}},
  151. },
  152. },
  153. "authz_allow_policy_2": {
  154. Principals: []*v3rbacpb.Principal{
  155. {Identifier: &v3rbacpb.Principal_Any{Any: true}},
  156. },
  157. Permissions: []*v3rbacpb.Permission{
  158. {Rule: &v3rbacpb.Permission_AndRules{AndRules: &v3rbacpb.Permission_Set{
  159. Rules: []*v3rbacpb.Permission{
  160. {Rule: &v3rbacpb.Permission_OrRules{OrRules: &v3rbacpb.Permission_Set{
  161. Rules: []*v3rbacpb.Permission{
  162. {Rule: &v3rbacpb.Permission_UrlPath{
  163. UrlPath: &v3matcherpb.PathMatcher{Rule: &v3matcherpb.PathMatcher_Path{Path: &v3matcherpb.StringMatcher{
  164. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "path-bar"},
  165. }}},
  166. }},
  167. {Rule: &v3rbacpb.Permission_UrlPath{
  168. UrlPath: &v3matcherpb.PathMatcher{Rule: &v3matcherpb.PathMatcher_Path{Path: &v3matcherpb.StringMatcher{
  169. MatchPattern: &v3matcherpb.StringMatcher_Suffix{Suffix: "baz"},
  170. }}},
  171. }},
  172. },
  173. }}},
  174. {Rule: &v3rbacpb.Permission_AndRules{AndRules: &v3rbacpb.Permission_Set{
  175. Rules: []*v3rbacpb.Permission{
  176. {Rule: &v3rbacpb.Permission_OrRules{OrRules: &v3rbacpb.Permission_Set{
  177. Rules: []*v3rbacpb.Permission{
  178. {Rule: &v3rbacpb.Permission_Header{
  179. Header: &v3routepb.HeaderMatcher{
  180. Name: "key-1", HeaderMatchSpecifier: &v3routepb.HeaderMatcher_ExactMatch{ExactMatch: "foo"},
  181. },
  182. }},
  183. {Rule: &v3rbacpb.Permission_Header{
  184. Header: &v3routepb.HeaderMatcher{
  185. Name: "key-1", HeaderMatchSpecifier: &v3routepb.HeaderMatcher_SuffixMatch{SuffixMatch: "bar"},
  186. },
  187. }},
  188. },
  189. }}},
  190. {Rule: &v3rbacpb.Permission_OrRules{OrRules: &v3rbacpb.Permission_Set{
  191. Rules: []*v3rbacpb.Permission{
  192. {Rule: &v3rbacpb.Permission_Header{
  193. Header: &v3routepb.HeaderMatcher{
  194. Name: "key-2", HeaderMatchSpecifier: &v3routepb.HeaderMatcher_PrefixMatch{PrefixMatch: "baz"},
  195. },
  196. }},
  197. },
  198. }}},
  199. },
  200. }}},
  201. },
  202. }}},
  203. },
  204. },
  205. },
  206. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{},
  207. },
  208. },
  209. wantPolicyName: "authz",
  210. },
  211. "allow authenticated": {
  212. authzPolicy: `{
  213. "name": "authz",
  214. "allow_rules": [
  215. {
  216. "name": "allow_authenticated",
  217. "source": {
  218. "principals":["*", ""]
  219. }
  220. }]
  221. }`,
  222. wantPolicies: []*v3rbacpb.RBAC{
  223. {
  224. Action: v3rbacpb.RBAC_ALLOW,
  225. Policies: map[string]*v3rbacpb.Policy{
  226. "authz_allow_authenticated": {
  227. Principals: []*v3rbacpb.Principal{
  228. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  229. Ids: []*v3rbacpb.Principal{
  230. {Identifier: &v3rbacpb.Principal_Authenticated_{
  231. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  232. MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}},
  233. }},
  234. }},
  235. {Identifier: &v3rbacpb.Principal_Authenticated_{
  236. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  237. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""},
  238. }},
  239. }},
  240. },
  241. }}},
  242. },
  243. Permissions: []*v3rbacpb.Permission{
  244. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  245. },
  246. },
  247. },
  248. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{},
  249. },
  250. },
  251. },
  252. "audit_logging_ALLOW empty config": {
  253. authzPolicy: `{
  254. "name": "authz",
  255. "allow_rules": [
  256. {
  257. "name": "allow_authenticated",
  258. "source": {
  259. "principals":["*", ""]
  260. }
  261. }],
  262. "deny_rules": [
  263. {
  264. "name": "deny_policy_1",
  265. "source": {
  266. "principals":[
  267. "spiffe://foo.abc"
  268. ]
  269. }
  270. }],
  271. "audit_logging_options": {
  272. "audit_condition": "ON_ALLOW",
  273. "audit_loggers": [
  274. {
  275. "name": "stdout_logger",
  276. "config": {},
  277. "is_optional": false
  278. }
  279. ]
  280. }
  281. }`,
  282. wantPolicies: []*v3rbacpb.RBAC{
  283. {
  284. Action: v3rbacpb.RBAC_DENY,
  285. Policies: map[string]*v3rbacpb.Policy{
  286. "authz_deny_policy_1": {
  287. Principals: []*v3rbacpb.Principal{
  288. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  289. Ids: []*v3rbacpb.Principal{
  290. {Identifier: &v3rbacpb.Principal_Authenticated_{
  291. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  292. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://foo.abc"},
  293. }},
  294. }},
  295. },
  296. }}},
  297. },
  298. Permissions: []*v3rbacpb.Permission{
  299. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  300. },
  301. },
  302. },
  303. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{
  304. AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE,
  305. LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
  306. {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]interface{}{}, "stdout_logger")},
  307. IsOptional: false,
  308. },
  309. },
  310. },
  311. },
  312. {
  313. Action: v3rbacpb.RBAC_ALLOW,
  314. Policies: map[string]*v3rbacpb.Policy{
  315. "authz_allow_authenticated": {
  316. Principals: []*v3rbacpb.Principal{
  317. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  318. Ids: []*v3rbacpb.Principal{
  319. {Identifier: &v3rbacpb.Principal_Authenticated_{
  320. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  321. MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}},
  322. }},
  323. }},
  324. {Identifier: &v3rbacpb.Principal_Authenticated_{
  325. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  326. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""},
  327. }},
  328. }},
  329. },
  330. }}},
  331. },
  332. Permissions: []*v3rbacpb.Permission{
  333. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  334. },
  335. },
  336. },
  337. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{
  338. AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_ON_ALLOW,
  339. LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
  340. {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]interface{}{}, "stdout_logger")},
  341. IsOptional: false,
  342. },
  343. },
  344. },
  345. },
  346. },
  347. },
  348. "audit_logging_DENY_AND_ALLOW": {
  349. authzPolicy: `{
  350. "name": "authz",
  351. "allow_rules": [
  352. {
  353. "name": "allow_authenticated",
  354. "source": {
  355. "principals":["*", ""]
  356. }
  357. }],
  358. "deny_rules": [
  359. {
  360. "name": "deny_policy_1",
  361. "source": {
  362. "principals":[
  363. "spiffe://foo.abc"
  364. ]
  365. }
  366. }],
  367. "audit_logging_options": {
  368. "audit_condition": "ON_DENY_AND_ALLOW",
  369. "audit_loggers": [
  370. {
  371. "name": "stdout_logger",
  372. "config": {},
  373. "is_optional": false
  374. }
  375. ]
  376. }
  377. }`,
  378. wantPolicies: []*v3rbacpb.RBAC{
  379. {
  380. Action: v3rbacpb.RBAC_DENY,
  381. Policies: map[string]*v3rbacpb.Policy{
  382. "authz_deny_policy_1": {
  383. Principals: []*v3rbacpb.Principal{
  384. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  385. Ids: []*v3rbacpb.Principal{
  386. {Identifier: &v3rbacpb.Principal_Authenticated_{
  387. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  388. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://foo.abc"},
  389. }},
  390. }},
  391. },
  392. }}},
  393. },
  394. Permissions: []*v3rbacpb.Permission{
  395. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  396. },
  397. },
  398. },
  399. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{
  400. AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_ON_DENY,
  401. LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
  402. {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]interface{}{}, "stdout_logger")},
  403. IsOptional: false,
  404. },
  405. },
  406. },
  407. },
  408. {
  409. Action: v3rbacpb.RBAC_ALLOW,
  410. Policies: map[string]*v3rbacpb.Policy{
  411. "authz_allow_authenticated": {
  412. Principals: []*v3rbacpb.Principal{
  413. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  414. Ids: []*v3rbacpb.Principal{
  415. {Identifier: &v3rbacpb.Principal_Authenticated_{
  416. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  417. MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}},
  418. }},
  419. }},
  420. {Identifier: &v3rbacpb.Principal_Authenticated_{
  421. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  422. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""},
  423. }},
  424. }},
  425. },
  426. }}},
  427. },
  428. Permissions: []*v3rbacpb.Permission{
  429. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  430. },
  431. },
  432. },
  433. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{
  434. AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_ON_DENY_AND_ALLOW,
  435. LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
  436. {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]interface{}{}, "stdout_logger")},
  437. IsOptional: false,
  438. },
  439. },
  440. },
  441. },
  442. },
  443. },
  444. "audit_logging_NONE": {
  445. authzPolicy: `{
  446. "name": "authz",
  447. "allow_rules": [
  448. {
  449. "name": "allow_authenticated",
  450. "source": {
  451. "principals":["*", ""]
  452. }
  453. }],
  454. "deny_rules": [
  455. {
  456. "name": "deny_policy_1",
  457. "source": {
  458. "principals":[
  459. "spiffe://foo.abc"
  460. ]
  461. }
  462. }],
  463. "audit_logging_options": {
  464. "audit_condition": "NONE",
  465. "audit_loggers": [
  466. {
  467. "name": "stdout_logger",
  468. "config": {},
  469. "is_optional": false
  470. }
  471. ]
  472. }
  473. }`,
  474. wantPolicies: []*v3rbacpb.RBAC{
  475. {
  476. Action: v3rbacpb.RBAC_DENY,
  477. Policies: map[string]*v3rbacpb.Policy{
  478. "authz_deny_policy_1": {
  479. Principals: []*v3rbacpb.Principal{
  480. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  481. Ids: []*v3rbacpb.Principal{
  482. {Identifier: &v3rbacpb.Principal_Authenticated_{
  483. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  484. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://foo.abc"},
  485. }},
  486. }},
  487. },
  488. }}},
  489. },
  490. Permissions: []*v3rbacpb.Permission{
  491. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  492. },
  493. },
  494. },
  495. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{
  496. AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE,
  497. LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
  498. {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]interface{}{}, "stdout_logger")},
  499. IsOptional: false,
  500. },
  501. },
  502. },
  503. },
  504. {
  505. Action: v3rbacpb.RBAC_ALLOW,
  506. Policies: map[string]*v3rbacpb.Policy{
  507. "authz_allow_authenticated": {
  508. Principals: []*v3rbacpb.Principal{
  509. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  510. Ids: []*v3rbacpb.Principal{
  511. {Identifier: &v3rbacpb.Principal_Authenticated_{
  512. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  513. MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}},
  514. }},
  515. }},
  516. {Identifier: &v3rbacpb.Principal_Authenticated_{
  517. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  518. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""},
  519. }},
  520. }},
  521. },
  522. }}},
  523. },
  524. Permissions: []*v3rbacpb.Permission{
  525. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  526. },
  527. },
  528. },
  529. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{
  530. AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE,
  531. LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
  532. {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]interface{}{}, "stdout_logger")},
  533. IsOptional: false,
  534. },
  535. },
  536. },
  537. },
  538. },
  539. },
  540. "audit_logging_custom_config simple": {
  541. authzPolicy: `{
  542. "name": "authz",
  543. "allow_rules": [
  544. {
  545. "name": "allow_authenticated",
  546. "source": {
  547. "principals":["*", ""]
  548. }
  549. }],
  550. "deny_rules": [
  551. {
  552. "name": "deny_policy_1",
  553. "source": {
  554. "principals":[
  555. "spiffe://foo.abc"
  556. ]
  557. }
  558. }],
  559. "audit_logging_options": {
  560. "audit_condition": "NONE",
  561. "audit_loggers": [
  562. {
  563. "name": "stdout_logger",
  564. "config": {"abc":123, "xyz":"123"},
  565. "is_optional": false
  566. }
  567. ]
  568. }
  569. }`,
  570. wantPolicies: []*v3rbacpb.RBAC{
  571. {
  572. Action: v3rbacpb.RBAC_DENY,
  573. Policies: map[string]*v3rbacpb.Policy{
  574. "authz_deny_policy_1": {
  575. Principals: []*v3rbacpb.Principal{
  576. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  577. Ids: []*v3rbacpb.Principal{
  578. {Identifier: &v3rbacpb.Principal_Authenticated_{
  579. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  580. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://foo.abc"},
  581. }},
  582. }},
  583. },
  584. }}},
  585. },
  586. Permissions: []*v3rbacpb.Permission{
  587. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  588. },
  589. },
  590. },
  591. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{
  592. AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE,
  593. LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
  594. {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]interface{}{"abc": 123, "xyz": "123"}, "stdout_logger")},
  595. IsOptional: false,
  596. },
  597. },
  598. },
  599. },
  600. {
  601. Action: v3rbacpb.RBAC_ALLOW,
  602. Policies: map[string]*v3rbacpb.Policy{
  603. "authz_allow_authenticated": {
  604. Principals: []*v3rbacpb.Principal{
  605. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  606. Ids: []*v3rbacpb.Principal{
  607. {Identifier: &v3rbacpb.Principal_Authenticated_{
  608. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  609. MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}},
  610. }},
  611. }},
  612. {Identifier: &v3rbacpb.Principal_Authenticated_{
  613. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  614. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""},
  615. }},
  616. }},
  617. },
  618. }}},
  619. },
  620. Permissions: []*v3rbacpb.Permission{
  621. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  622. },
  623. },
  624. },
  625. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{
  626. AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE,
  627. LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
  628. {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]interface{}{"abc": 123, "xyz": "123"}, "stdout_logger")},
  629. IsOptional: false,
  630. },
  631. },
  632. },
  633. },
  634. },
  635. },
  636. "audit_logging_custom_config nested": {
  637. authzPolicy: `{
  638. "name": "authz",
  639. "allow_rules": [
  640. {
  641. "name": "allow_authenticated",
  642. "source": {
  643. "principals":["*", ""]
  644. }
  645. }],
  646. "audit_logging_options": {
  647. "audit_condition": "NONE",
  648. "audit_loggers": [
  649. {
  650. "name": "stdout_logger",
  651. "config": {"abc":123, "xyz":{"abc":123}},
  652. "is_optional": false
  653. }
  654. ]
  655. }
  656. }`,
  657. wantPolicies: []*v3rbacpb.RBAC{
  658. {
  659. Action: v3rbacpb.RBAC_ALLOW,
  660. Policies: map[string]*v3rbacpb.Policy{
  661. "authz_allow_authenticated": {
  662. Principals: []*v3rbacpb.Principal{
  663. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  664. Ids: []*v3rbacpb.Principal{
  665. {Identifier: &v3rbacpb.Principal_Authenticated_{
  666. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  667. MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}},
  668. }},
  669. }},
  670. {Identifier: &v3rbacpb.Principal_Authenticated_{
  671. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  672. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""},
  673. }},
  674. }},
  675. },
  676. }}},
  677. },
  678. Permissions: []*v3rbacpb.Permission{
  679. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  680. },
  681. },
  682. },
  683. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{
  684. AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE,
  685. LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
  686. {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]interface{}{"abc": 123, "xyz": map[string]interface{}{"abc": 123}}, "stdout_logger")},
  687. IsOptional: false,
  688. },
  689. },
  690. },
  691. },
  692. },
  693. },
  694. "missing audit logger config": {
  695. authzPolicy: `{
  696. "name": "authz",
  697. "allow_rules": [
  698. {
  699. "name": "allow_authenticated",
  700. "source": {
  701. "principals":["*", ""]
  702. }
  703. }],
  704. "audit_logging_options": {
  705. "audit_condition": "NONE"
  706. }
  707. }`,
  708. wantPolicies: []*v3rbacpb.RBAC{
  709. {
  710. Action: v3rbacpb.RBAC_ALLOW,
  711. Policies: map[string]*v3rbacpb.Policy{
  712. "authz_allow_authenticated": {
  713. Principals: []*v3rbacpb.Principal{
  714. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  715. Ids: []*v3rbacpb.Principal{
  716. {Identifier: &v3rbacpb.Principal_Authenticated_{
  717. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  718. MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}},
  719. }},
  720. }},
  721. {Identifier: &v3rbacpb.Principal_Authenticated_{
  722. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  723. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""},
  724. }},
  725. }},
  726. },
  727. }}},
  728. },
  729. Permissions: []*v3rbacpb.Permission{
  730. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  731. },
  732. },
  733. },
  734. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{
  735. AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE,
  736. LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{},
  737. },
  738. },
  739. },
  740. },
  741. "missing audit condition": {
  742. authzPolicy: `{
  743. "name": "authz",
  744. "allow_rules": [
  745. {
  746. "name": "allow_authenticated",
  747. "source": {
  748. "principals":["*", ""]
  749. }
  750. }],
  751. "audit_logging_options": {
  752. "audit_loggers": [
  753. {
  754. "name": "stdout_logger",
  755. "config": {},
  756. "is_optional": false
  757. }
  758. ]
  759. }
  760. }`,
  761. wantPolicies: []*v3rbacpb.RBAC{
  762. {
  763. Action: v3rbacpb.RBAC_ALLOW,
  764. Policies: map[string]*v3rbacpb.Policy{
  765. "authz_allow_authenticated": {
  766. Principals: []*v3rbacpb.Principal{
  767. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  768. Ids: []*v3rbacpb.Principal{
  769. {Identifier: &v3rbacpb.Principal_Authenticated_{
  770. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  771. MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}},
  772. }},
  773. }},
  774. {Identifier: &v3rbacpb.Principal_Authenticated_{
  775. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  776. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""},
  777. }},
  778. }},
  779. },
  780. }}},
  781. },
  782. Permissions: []*v3rbacpb.Permission{
  783. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  784. },
  785. },
  786. },
  787. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{
  788. AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_NONE,
  789. LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
  790. {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]interface{}{}, "stdout_logger")},
  791. IsOptional: false,
  792. },
  793. },
  794. },
  795. },
  796. },
  797. },
  798. "missing custom config audit logger": {
  799. authzPolicy: `{
  800. "name": "authz",
  801. "allow_rules": [
  802. {
  803. "name": "allow_authenticated",
  804. "source": {
  805. "principals":["*", ""]
  806. }
  807. }],
  808. "deny_rules": [
  809. {
  810. "name": "deny_policy_1",
  811. "source": {
  812. "principals":[
  813. "spiffe://foo.abc"
  814. ]
  815. }
  816. }],
  817. "audit_logging_options": {
  818. "audit_condition": "ON_DENY",
  819. "audit_loggers": [
  820. {
  821. "name": "stdout_logger",
  822. "is_optional": false
  823. }
  824. ]
  825. }
  826. }`,
  827. wantPolicies: []*v3rbacpb.RBAC{
  828. {
  829. Action: v3rbacpb.RBAC_DENY,
  830. Policies: map[string]*v3rbacpb.Policy{
  831. "authz_deny_policy_1": {
  832. Principals: []*v3rbacpb.Principal{
  833. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  834. Ids: []*v3rbacpb.Principal{
  835. {Identifier: &v3rbacpb.Principal_Authenticated_{
  836. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  837. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: "spiffe://foo.abc"},
  838. }},
  839. }},
  840. },
  841. }}},
  842. },
  843. Permissions: []*v3rbacpb.Permission{
  844. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  845. },
  846. },
  847. },
  848. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{
  849. AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_ON_DENY,
  850. LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
  851. {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]interface{}{}, "stdout_logger")},
  852. IsOptional: false,
  853. },
  854. },
  855. },
  856. },
  857. {
  858. Action: v3rbacpb.RBAC_ALLOW,
  859. Policies: map[string]*v3rbacpb.Policy{
  860. "authz_allow_authenticated": {
  861. Principals: []*v3rbacpb.Principal{
  862. {Identifier: &v3rbacpb.Principal_OrIds{OrIds: &v3rbacpb.Principal_Set{
  863. Ids: []*v3rbacpb.Principal{
  864. {Identifier: &v3rbacpb.Principal_Authenticated_{
  865. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  866. MatchPattern: &v3matcherpb.StringMatcher_SafeRegex{SafeRegex: &v3matcherpb.RegexMatcher{Regex: ".+"}},
  867. }},
  868. }},
  869. {Identifier: &v3rbacpb.Principal_Authenticated_{
  870. Authenticated: &v3rbacpb.Principal_Authenticated{PrincipalName: &v3matcherpb.StringMatcher{
  871. MatchPattern: &v3matcherpb.StringMatcher_Exact{Exact: ""},
  872. }},
  873. }},
  874. },
  875. }}},
  876. },
  877. Permissions: []*v3rbacpb.Permission{
  878. {Rule: &v3rbacpb.Permission_Any{Any: true}},
  879. },
  880. },
  881. },
  882. AuditLoggingOptions: &v3rbacpb.RBAC_AuditLoggingOptions{
  883. AuditCondition: v3rbacpb.RBAC_AuditLoggingOptions_ON_DENY,
  884. LoggerConfigs: []*v3rbacpb.RBAC_AuditLoggingOptions_AuditLoggerConfig{
  885. {AuditLogger: &v3corepb.TypedExtensionConfig{Name: "stdout_logger", TypedConfig: anyPbHelper(t, map[string]interface{}{}, "stdout_logger")},
  886. IsOptional: false,
  887. },
  888. },
  889. },
  890. },
  891. },
  892. },
  893. "unknown field": {
  894. authzPolicy: `{"random": 123}`,
  895. wantErr: "failed to unmarshal policy",
  896. },
  897. "missing name field": {
  898. authzPolicy: `{}`,
  899. wantErr: `"name" is not present`,
  900. },
  901. "invalid field type": {
  902. authzPolicy: `{"name": 123}`,
  903. wantErr: "failed to unmarshal policy",
  904. },
  905. "missing allow rules field": {
  906. authzPolicy: `{"name": "authz-foo"}`,
  907. wantErr: `"allow_rules" is not present`,
  908. },
  909. "missing rule name field": {
  910. authzPolicy: `{
  911. "name": "authz-foo",
  912. "allow_rules": [{}]
  913. }`,
  914. wantErr: `"allow_rules" 0: "name" is not present`,
  915. },
  916. "missing header key": {
  917. authzPolicy: `{
  918. "name": "authz",
  919. "allow_rules": [{
  920. "name": "allow_policy_1",
  921. "request": {"headers":[{"key":"key-a", "values": ["value-a"]}, {}]}
  922. }]
  923. }`,
  924. wantErr: `"allow_rules" 0: "headers" 1: "key" is not present`,
  925. },
  926. "missing header values": {
  927. authzPolicy: `{
  928. "name": "authz",
  929. "allow_rules": [{
  930. "name": "allow_policy_1",
  931. "request": {"headers":[{"key":"key-a"}]}
  932. }]
  933. }`,
  934. wantErr: `"allow_rules" 0: "headers" 0: "values" is not present`,
  935. },
  936. "unsupported header": {
  937. authzPolicy: `{
  938. "name": "authz",
  939. "allow_rules": [{
  940. "name": "allow_policy_1",
  941. "request": {"headers":[{"key":":method", "values":["GET"]}]}
  942. }]
  943. }`,
  944. wantErr: `"allow_rules" 0: "headers" 0: unsupported "key" :method`,
  945. },
  946. "bad audit condition": {
  947. authzPolicy: `{
  948. "name": "authz",
  949. "allow_rules": [
  950. {
  951. "name": "allow_authenticated",
  952. "source": {
  953. "principals":["*", ""]
  954. }
  955. }],
  956. "audit_logging_options": {
  957. "audit_condition": "ABC",
  958. "audit_loggers": [
  959. {
  960. "name": "stdout_logger",
  961. "config": {},
  962. "is_optional": false
  963. }
  964. ]
  965. }
  966. }`,
  967. wantErr: `failed to parse AuditCondition ABC`,
  968. },
  969. "bad audit logger config": {
  970. authzPolicy: `{
  971. "name": "authz",
  972. "allow_rules": [
  973. {
  974. "name": "allow_authenticated",
  975. "source": {
  976. "principals":["*", ""]
  977. }
  978. }],
  979. "audit_logging_options": {
  980. "audit_condition": "NONE",
  981. "audit_loggers": [
  982. {
  983. "name": "stdout_logger",
  984. "config": "abc",
  985. "is_optional": false
  986. }
  987. ]
  988. }
  989. }`,
  990. wantErr: `failed to unmarshal policy`,
  991. },
  992. "missing audit logger name": {
  993. authzPolicy: `{
  994. "name": "authz",
  995. "allow_rules": [
  996. {
  997. "name": "allow_authenticated",
  998. "source": {
  999. "principals":["*", ""]
  1000. }
  1001. }],
  1002. "audit_logging_options": {
  1003. "audit_condition": "NONE",
  1004. "audit_loggers": [
  1005. {
  1006. "name": "",
  1007. "config": {},
  1008. "is_optional": false
  1009. }
  1010. ]
  1011. }
  1012. }`,
  1013. wantErr: `missing required field: name`,
  1014. },
  1015. }
  1016. for name, test := range tests {
  1017. t.Run(name, func(t *testing.T) {
  1018. gotPolicies, gotPolicyName, gotErr := translatePolicy(test.authzPolicy)
  1019. if gotErr != nil && !strings.HasPrefix(gotErr.Error(), test.wantErr) {
  1020. t.Fatalf("unexpected error\nwant:%v\ngot:%v", test.wantErr, gotErr)
  1021. }
  1022. if diff := cmp.Diff(gotPolicies, test.wantPolicies, protocmp.Transform()); diff != "" {
  1023. t.Fatalf("unexpected policy\ndiff (-want +got):\n%s", diff)
  1024. }
  1025. if test.wantPolicyName != "" && gotPolicyName != test.wantPolicyName {
  1026. t.Fatalf("unexpected policy name\nwant:%v\ngot:%v", test.wantPolicyName, gotPolicyName)
  1027. }
  1028. })
  1029. }
  1030. }
  1031. func anyPbHelper(t *testing.T, in map[string]interface{}, name string) *anypb.Any {
  1032. t.Helper()
  1033. pb, err := structpb.NewStruct(in)
  1034. typedStruct := &v1xdsudpatypepb.TypedStruct{
  1035. TypeUrl: typeURLPrefix + name,
  1036. Value: pb,
  1037. }
  1038. if err != nil {
  1039. t.Fatal(err)
  1040. }
  1041. customConfig, err := anypb.New(typedStruct)
  1042. if err != nil {
  1043. t.Fatal(err)
  1044. }
  1045. return customConfig
  1046. }