すべてのプロダクト
Search
ドキュメントセンター

:権限付与済みアクセス

最終更新日:Dec 22, 2023

権限付与済みアクセス

STS サービスの一時的な権限付与の使用

はじめに

Alibaba Cloud STS サービスにより、OSS はアクセスに対して一時的に権限を付与できます。Alibaba Cloud STS (Security Token Service) とは、クラウドコンピューティングユーザーに一時的なアクセストークンを提供する Web サービスです。STS を使用すると、権限と有効期間をカスタマイズしたアクセス資格情報をサードパーティ製のアプリケーションやフェデレーションユーザー (ユーザー ID を管理できます) に付与できます。サードパーティ製のアプリケーションやフェデレーションユーザーは、これらのアクセス資格情報を使用して、Alibaba Cloud プロダクトの API を直接呼び出したり、Alibaba Cloud プロダクトの SDK を使用してクラウドプロダクトの API にアクセスしたりできます。

  • サードパーティ製のアプリケーションに長期キー (AccessKey) を公開する必要はありません。アクセストークンを生成してサードパーティ製アプリケーションに送信するだけで済みます。このトークンのアクセス権限と有効期間はカスタマイズできます。
  • 権限の失効について気にかける必要もありません。アクセス資格情報は、有効期限が切れると自動的に無効になります。

アプリを例として、やり取りのプロセスを以下に示します。

このソリューションの詳細を以下に示します。

  1. アプリユーザーとしてログインします。アプリユーザーの ID はクライアントが管理します。クライアントは、ID 管理システムをカスタマイズすることも、外部の Web アカウントや OpenID を使用することもできます。AppServer で、有効なアプリユーザーごとに最小限のアクセス権限を細かく定義できます。
  2. AppServer が STS にセキュリティトークンをリクエストします。STS を呼び出す前に、アプリユーザーの最小限のアクセス権限 (ポリシー構文で記述) と権限付与の有効期限を決定する必要があります。決定したら、STS の AssumeRole インターフェイスを呼び出してセキュリティトークンを取得します。ロールの管理と使用方法の詳細については、『RAM ユーザーガイド』の「ロール」を参照してください。
  3. STS から AppServer に有効なアクセス資格情報が返されます。このアクセス資格情報には、セキュリティトークン、一時的なアクセスキー (AccessKeyId と AccessKeySecret)、有効期限が含まれます。
  4. AppServer から ClientApp にアクセス資格情報が返されます。ClientApp はこの資格情報をキャッシュします。資格情報が無効になったら、AppServer に新しい有効なアクセス資格情報をリクエストする必要があります。たとえば、アクセス資格情報の有効期間が 1 時間である場合、AppServer にアクセス資格情報の更新を 30 分ごとにリクエストできます。
  5. ClientApp は、ローカルにキャッシュしたアクセス資格情報を使用して Alibaba Cloud サービスの API をリクエストします。ECS は、STS のアクセス資格情報を認識し、STS を使用して資格情報を検証して、ユーザーリクエストに適切に応答します。

STS のセキュリティトークンの詳細については、『RAM ユーザーガイド』の「ロール」を参照してください。ここでのポイントは、STS の AssumeRole インターフェイスを呼び出すだけで有効なアクセス資格情報を取得できることです。このメソッドは、STS SDK を使用して呼び出すこともできます。詳細についてはこちらをクリックしてください

STS の資格情報を使用して署名付きリクエストを作成する

STS の一時的な資格情報を取得した後、ユーザーのクライアントは、含まれているセキュリティトークンと一時的なアクセスキー (AccessKeyId、AccessKeySecret) を使用して OSSClient を生成します。オブジェクトのアップロードを例として使用します。

String accessKeyId = "<accessKeyId>";
String accessKeySecret = "<accessKeySecret>";
String securityToken = "<securityToken>"
// Uses Hangzhou as an example
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";

OSSClient client = new OSSClient(endpoint, accessKeyId, accessKeySecret,securityToken);

シンプルな例

サーバーは許可されたリクエストを受信します。このリクエストでクライアント側のユーザー baymax はバケット MyAppStorage のパス user/baymax/ 内のオブジェクトへの書き込みを要求しています。

最初に、STS SDK を使用して、サーバーは以下に示す STS の一時的な資格情報コードを生成します。

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;

public class StsServiceSample {
  public static final String REGION_CN_HANGZHOU = "cn-hangzhou";
  public static final String STS_API_VERSION = "2015-04-01";
  public static final String STS_VERSION = "1";

  static AssumeRoleResponse assumeRole(String accessKeyId, String accessKeySecret,
                                       String roleArn, String roleSessionName, String policy, ProtocolType protocolType) throws ClientException {
    try {
      IClientProfile profile = DefaultProfile.getProfile(REGION_CN_HANGZHOU, accessKeyId, accessKeySecret);
      DefaultAcsClient client = new DefaultAcsClient(profile);

      final AssumeRoleRequest request = new AssumeRoleRequest();
      request.setVersion(STS_API_VERSION);
      request.setMethod(MethodType.POST);
      request.setProtocol(protocolType);

      request.setRoleArn(roleArn);
      request.setRoleSessionName(roleSessionName);
      request.setPolicy(policy);

      final AssumeRoleResponse response = client.getAcsResponse(request);

      return response;
    } catch (ClientException e) {
      throw e;
    }
  }
  public static void main(String[] args) {
    String accessKeyId = "o************F";
    String accessKeySecret = "y*******************U";
    String roleArn = "acs:ram::145883****900618:role/ossadminrole";
    String roleSessionName = "alice";
    String policy = "{\n" +
            "    \"Version\": \"1\", \n" +
            "    \"Statement\": [\n" +
            "        {\n" +
            "            \"Action\": [\n" +
            "                \"oss:GetBucket\", \n" +
            "                \"oss:GetObject\" \n" +
            "            ], \n" +
            "            \"Resource\": [\n" +
            "                \"acs:oss:*:177530****529849:mybucket\", \n" +
            "                \"acs:oss:*:177530****529849:mybucket/*\" \n" +
            "            ], \n" +
            "            \"Effect\": \"Allow\"\n" +
            "        }\n" +
            "    ]\n" +
            "}";
    ProtocolType protocolType = ProtocolType.HTTPS;

    try {
      final AssumeRoleResponse response = assumeRole(accessKeyId, accessKeySecret,
              roleArn, roleSessionName, policy, protocolType);

      System.out.println("Expiration: " + response.getCredentials().getExpiration());
      System.out.println("Access Key Id: " + response.getCredentials().getAccessKeyId());
      System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
      System.out.println("Security Token: " + response.getCredentials().getSecurityToken());
    } catch (ClientException e) {
      System.out.println("Failed to get a federation token.");
      System.out.println("Error code: " + e.getErrCode());
      System.out.println("Error message: " + e.getErrMsg());
    }

  }
}

クライアントはサーバーで生成された、上記の STS の一時的な資格情報を取得し、それを使用してデータを一度アップロードします。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSErrorCode;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.ServiceException;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.ObjectMetadata;

public class OSSObjectSample {


    public static void main(String[] args) throws Exception {
      String bucketName = "MyAppStorage";
      String filepath= "/user/baymax/";
        String accessKeyId = "<your STS access key id>";
        String accessKeySecret = "<your STS access key secret>";
        String securityToken = "<your STS securityToken>";
          String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
      String uploadFilePath = "d:/temp/photo.jpg";

      OSSClient client = new OSSClient(endpoint,accessKeyId,accessKeySecret,securityToken);
      File file = new File(uploadFilePath);
      InputStream content = new FileInputStream(file);
      // Creates Metadata for the object to upload
      ObjectMetadata meta = new ObjectMetadata();
      // You must set the ContentLength
      meta.setContentLength(file.length());
      String key=filepath+"photo.jpg";
      PutObjectResult result = client.putObject(bucketName, key, content, meta);
    }
}

URL 署名を使用したアクセス許可

署名付き URL の生成

署名付き URL を生成することにより、一時的なアクセス URL をユーザーに提供できます。URL を生成するときに、URL の有効期限を指定して、ユーザーがアクセスできる期間を制限できます。

署名付き URL の生成

コードは次のとおりです。

String bucketName = "your-bucket-name";
String key = "your-object-key";

// Sets the URL expiration time to 1 hour
Date expiration = new Date(new Date().getTime() + 3600 * 1000);

// Generates the URL
URL url = client.generatePresignedUrl(bucketName, key, expiration);

生成された URL はデフォルトで GET アクセスメソッドを使用します。このように、ブラウザーを直接使用して関連のコンテンツにアクセスできます。

他の HTTP メソッド URL の生成

ユーザーが他の操作 (オブジェクトのアップロードまたは削除など) を一時的に使用する場合は、別のメソッドで URL に署名する必要があります。例:

// Generates a PUT method URL
URL url = client.generatePresignedUrl(bucketName, key, expiration, HttpMethod.PUT);

HttpMethod.PUT パラメーターをインポートすると、生成された URL を使用してオブジェクトをアップロードできます。

ユーザー定義のパラメーター (UserMetadata) の追加

署名付き URL を生成してオブジェクトをアップロードし、UserMetadata、Content-Type、およびその他のヘッダーの情報を指定する場合は、次のように処理します。

// Creates request
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, key);

// Sets HttpMethod to PUT
generatePresignedUrlRequest.setMethod(HttpMethod.PUT);

// Adds UserMetadata
generatePresignedUrlRequest.addUserMetadata("author", "baymax");

// Adds Content-Type
request.setContentType("application/octet-stream");

// Generates signed URL
URL url = client.generatePresignedUrl(generatePresignedUrlRequest);

上記のプロセスでは署名付き URL の生成のみが行われます。リクエストヘッダーにメタ情報を追加する必要もあります。次のコードを参考にできます。

署名付き URL を使用したリクエストの送信

現在、Java SDK は Put Object と GET Object URL 署名リクエストをサポートします。

getobject URL 署名メソッドの使用

//The server generates the URL signature string
OSSClient Server  = new OSSClient(endpoint, accessId, accessKey);
Date expiration = DateUtil.parseRfc822Date("Wed, 18 Mar 2015 14:20:00 GMT");
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, key, HttpMethod.GET);
//Sets the expiration time
request.setExpiration(expiration);
// Generates the URL signature (HTTP GET request)
URL signedUrl = Server .generatePresignedUrl(request);
System.out.println("signed url for getObject: " + signedUrl);

//The client uses the URL signature string to send the request
OSSClient client  = new OSSClient(endpoint, "", "");
Map<String, String> customHeaders = new HashMap<String, String>();
// Adds the GetObject request header
customHeaders.put("Range", "bytes=100-1000");
OSSObject object = client.getObject(signedUrl,customHeaders);

putobject URL 署名メソッドの使用

//The server generates the URL signature string
OSSClient Server = new OSSClient(endpoint, accessId, accessKey);
Date expiration = DateUtil.parseRfc822Date("Wed, 18 Mar 2015 14:20:00 GMT");
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, key, HttpMethod.PUT);
//Sets the expiration time
request.setExpiration(expiration);
//Sets Content-Type
request.setContentType("application/octet-stream");
// Adds User Meta
request.addUserMetadata("author", "aliy");
// Generates the URL signature (HTTP PUT request)
URL signedUrl = Server.generatePresignedUrl(request);
System.out.println("signed url for putObject: " + signedUrl);

//The client uses the URL signature string to send the request
OSSClient client  = new OSSClient(endpoint, "", "");
File f = new File(filePath);
FileInputStream fin = new FileInputStream(f);
// Adds the PutObject request header
Map<String, String> customHeaders = new HashMap<String, String>();
customHeaders.put("Content-Type", "application/octet-stream");
// Adds User Meta
customHeaders.put("x-oss-meta-author", "aliy");
PutObjectResult result = client.putObject(signedUrl, fin, f.length(), customHeaders);