]>
git.proxmox.com Git - mirror_ovs.git/blob - ovsdb/rbac.c
2 * Copyright (c) 2017 Red Hat, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include "condition.h"
24 #include "condition.h"
27 #include "openvswitch/vlog.h"
28 #include "ovsdb-data.h"
29 #include "ovsdb-error.h"
30 #include "ovsdb-parser.h"
31 #include "ovsdb-util.h"
38 #include "transaction.h"
40 VLOG_DEFINE_THIS_MODULE(ovsdb_rbac
);
42 static const struct ovsdb_row
*
43 ovsdb_find_row_by_string_key(const struct ovsdb_table
*table
,
44 const char *column_name
,
47 const struct ovsdb_column
*column
;
48 column
= ovsdb_table_schema_get_column(table
->schema
, column_name
);
51 /* XXX This is O(n) in the size of the table. If the table has an
52 * index on the column, then we could implement it in O(1). */
53 const struct ovsdb_row
*row
;
54 HMAP_FOR_EACH (row
, hmap_node
, &table
->rows
) {
55 const struct ovsdb_datum
*datum
= &row
->fields
[column
->index
];
56 for (size_t i
= 0; i
< datum
->n
; i
++) {
57 if (datum
->keys
[i
].string
[0] &&
58 !strcmp(key
, datum
->keys
[i
].string
)) {
68 static const struct ovsdb_row
*
69 ovsdb_rbac_lookup_perms(const struct ovsdb
*db
, const char *role
,
72 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 1);
73 const struct ovsdb_row
*role_row
, *perm_row
;
74 const struct ovsdb_column
*column
;
76 /* Lookup role in roles table */
77 role_row
= ovsdb_find_row_by_string_key(db
->rbac_role
, "name", role
);
79 VLOG_INFO_RL(&rl
, "rbac: role \"%s\" not found in rbac roles table",
84 /* Find row in permissions column for table from "permissions" column */
85 column
= ovsdb_table_schema_get_column(role_row
->table
->schema
,
88 VLOG_INFO_RL(&rl
, "rbac: \"permissions\" column not present in rbac "
92 perm_row
= ovsdb_util_read_map_string_uuid_column(role_row
, "permissions",
99 ovsdb_rbac_authorized(const struct ovsdb_row
*perms
,
101 const struct ovsdb_row
*row
)
103 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 1);
104 const struct ovsdb_datum
*datum
;
107 datum
= ovsdb_util_get_datum(CONST_CAST(struct ovsdb_row
*, perms
),
109 OVSDB_TYPE_STRING
, OVSDB_TYPE_VOID
, UINT_MAX
);
112 VLOG_INFO_RL(&rl
, "rbac: error reading authorization column");
116 for (i
= 0; i
< datum
->n
; i
++) {
117 const char *name
= datum
->keys
[i
].string
;
118 const char *value
= NULL
;
121 if (name
[0] == '\0') {
122 /* empty string means all are authorized */
126 is_map
= strchr(name
, ':') != NULL
;
129 char *tmp
= xstrdup(name
);
130 char *col_name
, *key
, *save_ptr
= NULL
;
131 col_name
= strtok_r(tmp
, ":", &save_ptr
);
132 key
= strtok_r(NULL
, ":", &save_ptr
);
134 if (col_name
&& key
) {
135 value
= ovsdb_util_read_map_string_column(row
, col_name
, key
);
139 ovsdb_util_read_string_column(row
, name
, &value
);
141 if (value
&& !strcmp(value
, id
)) {
150 ovsdb_rbac_insert(const struct ovsdb
*db
, const struct ovsdb_table
*table
,
151 const struct ovsdb_row
*row
,
152 const char *role
, const char *id
)
154 const struct ovsdb_table_schema
*ts
= table
->schema
;
155 const struct ovsdb_row
*perms
;
158 if (!db
->rbac_role
|| !role
|| *role
== '\0') {
166 perms
= ovsdb_rbac_lookup_perms(db
, role
, ts
->name
);
172 if (!ovsdb_rbac_authorized(perms
, id
, row
)) {
176 if (!ovsdb_util_read_bool_column(perms
, "insert_delete", &insdel
)) {
188 struct rbac_delete_cbdata
{
189 const struct ovsdb_table
*table
;
190 const struct ovsdb_row
*perms
;
197 rbac_delete_cb(const struct ovsdb_row
*row
, void *rd_
)
199 struct rbac_delete_cbdata
*rd
= rd_
;
202 if (!ovsdb_rbac_authorized(rd
->perms
, rd
->id
, row
)) {
206 if (!ovsdb_util_read_bool_column(rd
->perms
, "insert_delete", &insdel
)) {
216 rd
->permitted
= false;
221 ovsdb_rbac_delete(const struct ovsdb
*db
, struct ovsdb_table
*table
,
222 struct ovsdb_condition
*condition
,
223 const char *role
, const char *id
)
225 const struct ovsdb_table_schema
*ts
= table
->schema
;
226 const struct ovsdb_row
*perms
;
227 struct rbac_delete_cbdata rd
;
229 if (!db
->rbac_role
|| !role
|| *role
== '\0') {
236 perms
= ovsdb_rbac_lookup_perms(db
, role
, ts
->name
);
248 ovsdb_query(table
, condition
, rbac_delete_cb
, &rd
);
258 struct rbac_update_cbdata
{
259 const struct ovsdb_table
*table
;
260 const struct ovsdb_column_set
*columns
; /* columns to be modified */
261 const struct ovsdb_datum
*modifiable
; /* modifiable column names */
262 const struct ovsdb_row
*perms
;
269 rbac_column_modification_permitted(const struct ovsdb_column
*column
,
270 const struct ovsdb_datum
*modifiable
)
274 for (i
= 0; i
< modifiable
->n
; i
++) {
275 char *name
= modifiable
->keys
[i
].string
;
277 if (!strcmp(name
, column
->name
)) {
285 rbac_update_cb(const struct ovsdb_row
*row
, void *ru_
)
287 struct rbac_update_cbdata
*ru
= ru_
;
290 if (!ovsdb_rbac_authorized(ru
->perms
, ru
->id
, row
)) {
294 for (i
= 0; i
< ru
->columns
->n_columns
; i
++) {
295 const struct ovsdb_column
*column
= ru
->columns
->columns
[i
];
297 if (!rbac_column_modification_permitted(column
, ru
->modifiable
)) {
304 ru
->permitted
= false;
309 ovsdb_rbac_update(const struct ovsdb
*db
,
310 struct ovsdb_table
*table
,
311 struct ovsdb_column_set
*columns
,
312 struct ovsdb_condition
*condition
,
313 const char *role
, const char *id
)
315 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 1);
316 const struct ovsdb_table_schema
*ts
= table
->schema
;
317 const struct ovsdb_datum
*datum
;
318 const struct ovsdb_row
*perms
;
319 struct rbac_update_cbdata ru
;
321 if (!db
->rbac_role
|| !role
|| *role
== '\0') {
328 perms
= ovsdb_rbac_lookup_perms(db
, role
, ts
->name
);
334 datum
= ovsdb_util_get_datum(CONST_CAST(struct ovsdb_row
*, perms
),
336 OVSDB_TYPE_STRING
, OVSDB_TYPE_VOID
, UINT_MAX
);
339 VLOG_INFO_RL(&rl
, "ovsdb_rbac_update: could not read \"update\" "
345 ru
.columns
= columns
;
349 ru
.modifiable
= datum
;
352 ovsdb_query(table
, condition
, rbac_update_cb
, &ru
);
362 struct rbac_mutate_cbdata
{
363 const struct ovsdb_table
*table
;
364 const struct ovsdb_mutation_set
*mutations
; /* columns to be mutated */
365 const struct ovsdb_datum
*modifiable
; /* modifiable column names */
366 const struct ovsdb_row
*perms
;
373 rbac_mutate_cb(const struct ovsdb_row
*row
, void *rm_
)
375 struct rbac_mutate_cbdata
*rm
= rm_
;
378 if (!ovsdb_rbac_authorized(rm
->perms
, rm
->id
, row
)) {
382 for (i
= 0; i
< rm
->mutations
->n_mutations
; i
++) {
383 const struct ovsdb_column
*column
= rm
->mutations
->mutations
[i
].column
;
385 if (!rbac_column_modification_permitted(column
, rm
->modifiable
)) {
393 rm
->permitted
= false;
398 ovsdb_rbac_mutate(const struct ovsdb
*db
,
399 struct ovsdb_table
*table
,
400 struct ovsdb_mutation_set
*mutations
,
401 struct ovsdb_condition
*condition
,
402 const char *role
, const char *id
)
404 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 1);
405 const struct ovsdb_table_schema
*ts
= table
->schema
;
406 const struct ovsdb_datum
*datum
;
407 const struct ovsdb_row
*perms
;
408 struct rbac_mutate_cbdata rm
;
410 if (!db
->rbac_role
|| !role
|| *role
== '\0') {
417 perms
= ovsdb_rbac_lookup_perms(db
, role
, ts
->name
);
423 datum
= ovsdb_util_get_datum(CONST_CAST(struct ovsdb_row
*, perms
),
425 OVSDB_TYPE_STRING
, OVSDB_TYPE_VOID
, UINT_MAX
);
428 VLOG_INFO_RL(&rl
, "ovsdb_rbac_mutate: could not read \"update\" "
434 rm
.mutations
= mutations
;
438 rm
.modifiable
= datum
;
441 ovsdb_query(table
, condition
, rbac_mutate_cb
, &rm
);