RGW中的请求的认证过程

原创 2015年11月17日 20:35:50

RGW中的用户认证过程(keystone or rados backend)

用户s3用户请求的合法性验证过程:src/rgw/rgw_rest_s3.cc
Rgw的认证方式有两种一个是使用keystone认证;一个是使用rados自带的认证方式;根据配置判断是否使用keystone认证;如果配置了keystone方式,则keystone方式;(二选一)

int RGW_Auth_S3::authorize(RGWRados *store, struct req_state *s)
{
  bool qsr = false;
  string auth_id;
  string auth_sign;

  time_t now;
  time(&now);

  /* neither keystone and rados enabled; warn and exit! */
  if (!store->ctx()->_conf->rgw_s3_auth_use_rados
      && !store->ctx()->_conf->rgw_s3_auth_use_keystone) {
    dout(0) << "WARNING: no authorization backend enabled! Users will never authenticate." << dendl;
    return -EPERM;
  }

  if (s->op == OP_OPTIONS) {
    init_anon_user(s);
    return 0;
  }
/* initialize auth_id and auth_sign */
  if (!s->http_auth || !(*s->http_auth)) {
    auth_id = s->info.args.get("AWSAccessKeyId");
    if (auth_id.size()) {
      auth_sign = s->info.args.get("Signature");

      string date = s->info.args.get("Expires");
      time_t exp = atoll(date.c_str());
      if (now >= exp)
        return -EPERM;

      qsr = true;
    } else {
      /* anonymous access */
      init_anon_user(s);
      return 0;
    }
  } else {
    if (strncmp(s->http_auth, "AWS ", 4))
      return -EINVAL;
    string auth_str(s->http_auth + 4);
    int pos = auth_str.rfind(':');
    if (pos < 0)
      return -EINVAL;

    auth_id = auth_str.substr(0, pos);
    auth_sign = auth_str.substr(pos + 1);
  }

  /* try keystone auth first */
  int keystone_result = -EINVAL;
  if (store->ctx()->_conf->rgw_s3_auth_use_keystone
      && !store->ctx()->_conf->rgw_keystone_url.empty()) {
    dout(20) << "s3 keystone: trying keystone auth" << dendl;
//构造keystone验证的验证器。
    RGW_Auth_S3_Keystone_ValidateToken keystone_validator(store->ctx());
    string token;
//获取用于计算签名的请求头信息(s3认证)
    if (!rgw_create_s3_canonical_header(s->info, &s->header_time, token, qsr)) {
        dout(10) << "failed to create auth header\n" << token << dendl;
    } else {
      keystone_result = keystone_validator.validate_s3token(auth_id, token, auth_sign);
      if (keystone_result == 0) {
    // Check for time skew first
    time_t req_sec = s->header_time.sec();

    if ((req_sec < now - RGW_AUTH_GRACE_MINS * 60 ||
         req_sec > now + RGW_AUTH_GRACE_MINS * 60) && !qsr) {
      dout(10) << "req_sec=" << req_sec << " now=" << now << "; now - RGW_AUTH_GRACE_MINS=" << now - RGW_AUTH_GRACE_MINS * 60 << "; now + RGW_AUTH_GRACE_MINS=" << now + RGW_AUTH_GRACE_MINS * 60 << dendl;
      dout(0) << "NOTICE: request time skew too big now=" << utime_t(now, 0) << " req_time=" << s->header_time << dendl;
      return -ERR_REQUEST_TIME_SKEWED;
    }


    s->user.user_id = keystone_validator.response.token.tenant.id;
        s->user.display_name = keystone_validator.response.token.tenant.name; // wow.

        /* try to store user if it not already exists */
        if (rgw_get_user_info_by_uid(store, keystone_validator.response.token.tenant.id, s->user) < 0) {
          int ret = rgw_store_user_info(store, s->user, NULL, NULL, 0, true);
          if (ret < 0)
            dout(10) << "NOTICE: failed to store new user's info: ret=" << ret << dendl;
        }

        s->perm_mask = RGW_PERM_FULL_CONTROL;
      }
    }
  }

  /* keystone failed (or not enabled); check if we want to use rados backend */
  if (!store->ctx()->_conf->rgw_s3_auth_use_rados
      && keystone_result < 0)
    return keystone_result;

  /* now try rados backend, but only if keystone did not succeed */
  if (keystone_result < 0) {
    /* get the user info */
    if (rgw_get_user_info_by_access_key(store, auth_id, s->user) < 0) {
      dout(5) << "error reading user info, uid=" << auth_id << " can't authenticate" << dendl;
      return -ERR_INVALID_ACCESS_KEY;
    }

    /* now verify signature */

string auth_hdr;
//生成s3token
    if (!rgw_create_s3_canonical_header(s->info, &s->header_time, auth_hdr, qsr)) {
      dout(10) << "failed to create auth header\n" << auth_hdr << dendl;
      return -EPERM;
    }
    dout(10) << "auth_hdr:\n" << auth_hdr << dendl;

    time_t req_sec = s->header_time.sec();
    if ((req_sec < now - RGW_AUTH_GRACE_MINS * 60 ||
        req_sec > now + RGW_AUTH_GRACE_MINS * 60) && !qsr) {
      dout(10) << "req_sec=" << req_sec << " now=" << now << "; now - RGW_AUTH_GRACE_MINS=" << now - RGW_AUTH_GRACE_MINS * 60 << "; now + RGW_AUTH_GRACE_MINS=" << now + RGW_AUTH_GRACE_MINS * 60 << dendl;
      dout(0) << "NOTICE: request time skew too big now=" << utime_t(now, 0) << " req_time=" << s->header_time << dendl;
      return -ERR_REQUEST_TIME_SKEWED;
    }

    map<string, RGWAccessKey>::iterator iter = s->user.access_keys.find(auth_id);
    if (iter == s->user.access_keys.end()) {
      dout(0) << "ERROR: access key not encoded in user info" << dendl;
      return -EPERM;
    }
    RGWAccessKey& k = iter->second;

    if (!k.subuser.empty()) {
      map<string, RGWSubUser>::iterator uiter = s->user.subusers.find(k.subuser);
      if (uiter == s->user.subusers.end()) {
        dout(0) << "NOTICE: could not find subuser: " << k.subuser << dendl;
        return -EPERM;
      }
      RGWSubUser& subuser = uiter->second;
      s->perm_mask = subuser.perm_mask;
    } else
      s->perm_mask = RGW_PERM_FULL_CONTROL;

string digest;
//生成s3 token
    int ret = rgw_get_s3_header_digest(auth_hdr, k.key, digest);
    if (ret < 0) {
      return -EPERM;
    }

    dout(15) << "calculated digest=" << digest << dendl;
    dout(15) << "auth_sign=" << auth_sign << dendl;
    dout(15) << "compare=" << auth_sign.compare(digest) << dendl;

    if (auth_sign != digest) {
      return -ERR_SIGNATURE_NO_MATCH;
    }

    if (s->user.system) {
      s->system_request = true;
      dout(20) << "system request" << dendl;
      s->info.args.set_system();
      string effective_uid = s->info.args.get(RGW_SYS_PARAM_PREFIX "uid");
      RGWUserInfo effective_user;
      if (!effective_uid.empty()) {
        ret = rgw_get_user_info_by_uid(store, effective_uid, effective_user);
        if (ret < 0) {
          ldout(s->cct, 0) << "User lookup failed!" << dendl;
          return -ENOENT;
        }
        s->user = effective_user;
      }
    }

  } /* if keystone_result < 0 */

  // populate the owner info
  s->owner.set_id(s->user.user_id);
  s->owner.set_name(s->user.display_name);

  return  0;
}

radosgw layout (rgw 布局)

要了解一个存储系统,首先要了解其数据、元数据布局、重要抽象。这里对radosgw / rgw 的布局进行简单介绍。...
  • ganggexiongqi
  • ganggexiongqi
  • 2016年05月19日 11:53
  • 1494

三种Ceph rgw前端的配置方式

rgw 概述Ceph 通过radosgw提供RESTFul HTTP API接口支持对象存储能力,radosgw构建在librados之上,兼容Amazon S3以及Opensack Swift。ra...
  • lzw06061139
  • lzw06061139
  • 2016年05月18日 16:47
  • 5885

CEPH RGW 使用

创建一个S3风格用法的用户 ceph-admin-node@ceph-admin-node:~$ sudo radosgw-admin user create id=”harvis_rgw_user...
  • jiankangshiye
  • jiankangshiye
  • 2017年04月17日 18:58
  • 682

【实践】RGW+Ganesha环境部署

目前,Ganesha支持两种方式将Ceph导出为NFS,一种是基于CephFS——Ganesha通过FSAL-CEPH模块连接到CephFS,另一种是基于RGW——Ganesha通过FSAL-RGW模...
  • iamonlyme
  • iamonlyme
  • 2017年06月18日 15:58
  • 1799

CEPH RGW处理请求过程

Rgw处理请求过程Rest api: Put /{bucket} HTTP/1.1 x-amz-acl: public-read-write Authorization: AWS {access}...
  • litianze99
  • litianze99
  • 2015年11月17日 20:29
  • 2007

RGW Create bucket

RGW Create bucket client 提交一个的请求后,daemon会实例化一个handler来处理该请求,如创建一个bucket。 daemon会实例一个RGWHandler_Obj...
  • litianze99
  • litianze99
  • 2016年02月14日 19:14
  • 636

RGW处理请求中获取handler过程

RGW 创建处理请求的handler在src/rgw/rgw_main.cc源文件中的process_request()函数中有一个很重要的操作,就是Handler的获取,handler是manage...
  • litianze99
  • litianze99
  • 2015年11月17日 20:32
  • 803

Ceph Object Gateway与keystone集成

简介 Ceph Object Gateway与keystone集成用于用户认证服务是ceph本身都支持的一个扩展,keystone是openstack项目中的一个子项目,主要担负用户身份认证及服务分类...
  • litianze99
  • litianze99
  • 2015年08月19日 14:54
  • 1786

Ceph部署(二)RGW搭建

背景Ceph RGW简介Ceph RGW基于librados,是为应用提供RESTful类型的对象存储接口。RGW提供两种类型的接口:   1) S3:兼容Amazon S3RESTful API;...
  • styshoo
  • styshoo
  • 2017年02月28日 06:39
  • 827

CEPH RGW处理请求过程

Rgw处理请求过程Rest api: Put /{bucket} HTTP/1.1 x-amz-acl: public-read-write Authorization: AWS {access}...
  • litianze99
  • litianze99
  • 2015年11月17日 20:29
  • 2007
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:RGW中的请求的认证过程
举报原因:
原因补充:

(最多只允许输入30个字)