]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_opa.cc
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / rgw / rgw_opa.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 #include "rgw_opa.h"
5 #include "rgw_http_client.h"
6
7 #define dout_context g_ceph_context
8 #define dout_subsys ceph_subsys_rgw
9
10 using namespace std;
11
12 int rgw_opa_authorize(RGWOp *& op,
13 req_state * const s)
14 {
15
16 ldpp_dout(op, 2) << "authorizing request using OPA" << dendl;
17
18 /* get OPA url */
19 const string& opa_url = s->cct->_conf->rgw_opa_url;
20 if (opa_url == "") {
21 ldpp_dout(op, 2) << "OPA_URL not provided" << dendl;
22 return -ERR_INVALID_REQUEST;
23 }
24 ldpp_dout(op, 2) << "OPA URL= " << opa_url.c_str() << dendl;
25
26 /* get authentication token for OPA */
27 const string& opa_token = s->cct->_conf->rgw_opa_token;
28
29 int ret;
30 bufferlist bl;
31 RGWHTTPTransceiver req(s->cct, "POST", opa_url.c_str(), &bl);
32
33 /* set required headers for OPA request */
34 req.append_header("X-Auth-Token", opa_token);
35 req.append_header("Content-Type", "application/json");
36 req.append_header("Expect", "100-continue");
37
38 /* check if we want to verify OPA server SSL certificate */
39 req.set_verify_ssl(s->cct->_conf->rgw_opa_verify_ssl);
40
41 /* create json request body */
42 JSONFormatter jf;
43 jf.open_object_section("");
44 jf.open_object_section("input");
45 const char *request_method = s->info.env->get("REQUEST_METHOD");
46 if (request_method) {
47 jf.dump_string("method", request_method);
48 }
49 jf.dump_string("relative_uri", s->relative_uri.c_str());
50 jf.dump_string("decoded_uri", s->decoded_uri.c_str());
51 jf.dump_string("params", s->info.request_params.c_str());
52 jf.dump_string("request_uri_aws4", s->info.request_uri_aws4.c_str());
53 if (s->object) {
54 jf.dump_string("object_name", s->object->get_name().c_str());
55 }
56 if (s->auth.identity) {
57 jf.dump_string("subuser", s->auth.identity->get_subuser().c_str());
58 }
59 if (s->user) {
60 jf.dump_object("user_info", s->user->get_info());
61 }
62 if (s->bucket) {
63 jf.dump_object("bucket_info", s->bucket->get_info());
64 }
65 jf.close_section();
66 jf.close_section();
67
68 std::stringstream ss;
69 jf.flush(ss);
70 req.set_post_data(ss.str());
71 req.set_send_length(ss.str().length());
72
73 /* send request */
74 ret = req.process(null_yield);
75 if (ret < 0) {
76 ldpp_dout(op, 2) << "OPA process error:" << bl.c_str() << dendl;
77 return ret;
78 }
79
80 /* check OPA response */
81 JSONParser parser;
82 if (!parser.parse(bl.c_str(), bl.length())) {
83 ldpp_dout(op, 2) << "OPA parse error: malformed json" << dendl;
84 return -EINVAL;
85 }
86
87 bool opa_result;
88 JSONDecoder::decode_json("result", opa_result, &parser);
89
90 if (opa_result == false) {
91 ldpp_dout(op, 2) << "OPA rejecting request" << dendl;
92 return -EPERM;
93 }
94
95 ldpp_dout(op, 2) << "OPA accepting request" << dendl;
96 return 0;
97 }