mirror of
https://github.com/ceph/ceph
synced 2024-12-15 16:07:00 +00:00
Merge pull request #16442 from theanalyst/rgw-admin-tenant-validate
rgw: validate tenant names during user create. Reviewed-by: Casey Bodley <cbodley@redhat.com> Reviewed-by: Pritha Srivastava <prsrivas@redhat.com>
This commit is contained in:
commit
0a3056df4a
@ -321,6 +321,11 @@ generated key is added to the keyring without replacing an existing key pair.
|
||||
If ``access-key`` is specified and refers to an existing key owned by the user
|
||||
then it will be modified.
|
||||
|
||||
.. versionadded:: Luminous
|
||||
|
||||
A ``tenant`` may either be specified as a part of uid or as an additional
|
||||
request param.
|
||||
|
||||
:caps: users=write
|
||||
|
||||
Syntax
|
||||
@ -342,6 +347,7 @@ Request Parameters
|
||||
:Type: String
|
||||
:Example: ``foo_user``
|
||||
:Required: Yes
|
||||
A tenant name may also specified as a part of ``uid``, by following the syntax ``tenant$user``, refer to `Multitenancy`_ for more details.
|
||||
|
||||
``display-name``
|
||||
|
||||
@ -408,6 +414,14 @@ Request Parameters
|
||||
:Example: False [False]
|
||||
:Required: No
|
||||
|
||||
.. versionadded:: Jewel
|
||||
``tenant``
|
||||
|
||||
:Description: the Tenant under which a user is a part of.
|
||||
:Type: string
|
||||
:Example: tenant1
|
||||
:Required: No
|
||||
|
||||
Response Entities
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -418,6 +432,11 @@ If successful, the response contains the user information.
|
||||
:Description: A container for the user data information.
|
||||
:Type: Container
|
||||
|
||||
``tenant``
|
||||
:Description: The tenant which user is a part of
|
||||
:Type: String
|
||||
:Parent: ``user``
|
||||
|
||||
``user_id``
|
||||
|
||||
:Description: The user id.
|
||||
@ -1924,3 +1943,4 @@ Standard Error Responses
|
||||
|
||||
.. _Admin Guide: ../admin
|
||||
.. _Quota Management: ../admin#quota-management
|
||||
.. _Multitenancy: ./multitenancy
|
||||
|
@ -4435,6 +4435,9 @@ int main(int argc, const char **argv)
|
||||
ret = user.add(user_op, &err_msg);
|
||||
if (ret < 0) {
|
||||
cerr << "could not create user: " << err_msg << std::endl;
|
||||
if (ret == -ERR_INVALID_TENANT_NAME)
|
||||
ret = -EINVAL;
|
||||
|
||||
return -ret;
|
||||
}
|
||||
if (!subuser.empty()) {
|
||||
|
@ -1834,18 +1834,6 @@ int RGWHandler_REST::allocate_formatter(struct req_state *s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RGWHandler_REST::validate_tenant_name(string const& t)
|
||||
{
|
||||
struct tench {
|
||||
static bool is_good(char ch) {
|
||||
return isalnum(ch) || ch == '_';
|
||||
}
|
||||
};
|
||||
std::string::const_iterator it =
|
||||
std::find_if_not(t.begin(), t.end(), tench::is_good);
|
||||
return (it == t.end())? 0: -ERR_INVALID_TENANT_NAME;
|
||||
}
|
||||
|
||||
// This function enforces Amazon's spec for bucket names.
|
||||
// (The requirements, not the recommendations.)
|
||||
int RGWHandler_REST::validate_bucket_name(const string& bucket)
|
||||
|
@ -501,7 +501,6 @@ public:
|
||||
RGWHandler_REST() {}
|
||||
~RGWHandler_REST() override {}
|
||||
|
||||
static int validate_tenant_name(const string& bucket);
|
||||
static int validate_bucket_name(const string& bucket);
|
||||
static int validate_object_name(const string& object);
|
||||
|
||||
|
@ -3206,7 +3206,7 @@ int RGWHandler_REST_S3::postauth_init()
|
||||
<< " s->bucket=" << rgw_make_bucket_entry_name(s->bucket_tenant, s->bucket_name) << dendl;
|
||||
|
||||
int ret;
|
||||
ret = validate_tenant_name(s->bucket_tenant);
|
||||
ret = rgw_validate_tenant_name(s->bucket_tenant);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!s->bucket_name.empty()) {
|
||||
@ -3221,7 +3221,7 @@ int RGWHandler_REST_S3::postauth_init()
|
||||
if (!t->src_bucket.empty()) {
|
||||
rgw_parse_url_bucket(t->src_bucket, s->user->user_id.tenant,
|
||||
s->src_tenant_name, s->src_bucket_name);
|
||||
ret = validate_tenant_name(s->src_tenant_name);
|
||||
ret = rgw_validate_tenant_name(s->src_tenant_name);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = valid_s3_bucket_name(s->src_bucket_name, relaxed_names);
|
||||
@ -3237,8 +3237,8 @@ int RGWHandler_REST_S3::init(RGWRados *store, struct req_state *s,
|
||||
int ret;
|
||||
|
||||
s->dialect = "s3";
|
||||
|
||||
ret = validate_tenant_name(s->bucket_tenant);
|
||||
|
||||
ret = rgw_validate_tenant_name(s->bucket_tenant);
|
||||
if (ret)
|
||||
return ret;
|
||||
bool relaxed_names = s->cct->_conf->rgw_relaxed_s3_bucket_names;
|
||||
|
@ -2558,7 +2558,7 @@ int RGWHandler_REST_SWIFT::postauth_init()
|
||||
<< dendl;
|
||||
|
||||
int ret;
|
||||
ret = validate_tenant_name(s->bucket_tenant);
|
||||
ret = rgw_validate_tenant_name(s->bucket_tenant);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = validate_bucket_name(s->bucket_name);
|
||||
|
@ -76,6 +76,7 @@ void RGWOp_User_Create::execute()
|
||||
std::string secret_key;
|
||||
std::string key_type_str;
|
||||
std::string caps;
|
||||
std::string tenant_name;
|
||||
|
||||
bool gen_key;
|
||||
bool suspended;
|
||||
@ -96,6 +97,7 @@ void RGWOp_User_Create::execute()
|
||||
RESTArgs::get_string(s, "secret-key", secret_key, &secret_key);
|
||||
RESTArgs::get_string(s, "key-type", key_type_str, &key_type_str);
|
||||
RESTArgs::get_string(s, "user-caps", caps, &caps);
|
||||
RESTArgs::get_string(s, "tenant", tenant_name, &tenant_name);
|
||||
RESTArgs::get_bool(s, "generate-key", true, &gen_key);
|
||||
RESTArgs::get_bool(s, "suspended", false, &suspended);
|
||||
RESTArgs::get_int32(s, "max-buckets", default_max_buckets, &max_buckets);
|
||||
@ -108,6 +110,10 @@ void RGWOp_User_Create::execute()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tenant_name.empty()) {
|
||||
uid.tenant = tenant_name;
|
||||
}
|
||||
|
||||
// TODO: validate required args are passed in. (for eg. uid and display_name here)
|
||||
op_state.set_user_id(uid);
|
||||
op_state.set_display_name(display_name);
|
||||
|
@ -578,6 +578,18 @@ uint32_t rgw_str_to_perm(const char *str)
|
||||
return RGW_PERM_INVALID;
|
||||
}
|
||||
|
||||
int rgw_validate_tenant_name(const string& t)
|
||||
{
|
||||
struct tench {
|
||||
static bool is_good(char ch) {
|
||||
return isalnum(ch) || ch == '_';
|
||||
}
|
||||
};
|
||||
std::string::const_iterator it =
|
||||
std::find_if_not(t.begin(), t.end(), tench::is_good);
|
||||
return (it == t.end())? 0: -ERR_INVALID_TENANT_NAME;
|
||||
}
|
||||
|
||||
static bool validate_access_key(string& key)
|
||||
{
|
||||
const char *p = key.c_str();
|
||||
@ -1886,6 +1898,13 @@ int RGWUser::check_op(RGWUserAdminOpState& op_state, std::string *err_msg)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int ret = rgw_validate_tenant_name(op_id.tenant);
|
||||
if (ret) {
|
||||
set_err_msg(err_msg,
|
||||
"invalid tenant only alphanumeric and _ characters are allowed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
//set key type when it not set or set by context
|
||||
if ((op_state.get_key_type() < 0) || op_state.key_type_setbycontext) {
|
||||
op_state.set_key_type(KEY_TYPE_S3);
|
||||
|
@ -115,9 +115,6 @@ extern int rgw_get_user_attrs_by_uid(RGWRados *store,
|
||||
* Given an RGWUserInfo, deletes the user and its bucket ACLs.
|
||||
*/
|
||||
extern int rgw_delete_user(RGWRados *store, RGWUserInfo& user, RGWObjVersionTracker& objv_tracker);
|
||||
/**
|
||||
* Store a list of the user's buckets, with associated functinos.
|
||||
*/
|
||||
|
||||
/*
|
||||
* remove the different indexes
|
||||
@ -127,14 +124,11 @@ extern int rgw_remove_uid_index(RGWRados *store, rgw_user& uid);
|
||||
extern int rgw_remove_email_index(RGWRados *store, string& email);
|
||||
extern int rgw_remove_swift_name_index(RGWRados *store, string& swift_name);
|
||||
|
||||
/*
|
||||
* An RGWUser class along with supporting classes created
|
||||
* to support the creation of an RESTful administrative API
|
||||
*/
|
||||
|
||||
extern void rgw_perm_to_str(uint32_t mask, char *buf, int len);
|
||||
extern uint32_t rgw_str_to_perm(const char *str);
|
||||
|
||||
extern int rgw_validate_tenant_name(const string& t);
|
||||
|
||||
enum ObjectKeyType {
|
||||
KEY_TYPE_SWIFT,
|
||||
KEY_TYPE_S3,
|
||||
@ -153,6 +147,10 @@ enum RGWUserId {
|
||||
RGW_ACCESS_KEY,
|
||||
};
|
||||
|
||||
/*
|
||||
* An RGWUser class along with supporting classes created
|
||||
* to support the creation of an RESTful administrative API
|
||||
*/
|
||||
struct RGWUserAdminOpState {
|
||||
// user attributes
|
||||
RGWUserInfo info;
|
||||
|
Loading…
Reference in New Issue
Block a user