翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
SIGv4 Amazon Lattice VPC の認証されたリクエスト
VPC Lattice は、クライアント認証に Signature Version 4 (SIGv4) または Signature Version 4A (SIGv4A) を使用します。詳細については、IAM「 ユーザーガイドAWS API」の「リクエストの署名」を参照してください。
考慮事項
-
VPC Lattice は、 SIGv4または で署名されたリクエストを認証しようとしますSIGv4A。認証なしではリクエストは失敗します。
-
VPC Lattice はペイロード署名をサポートしていません。
x-amz-content-sha256
ヘッダーの値を"UNSIGNED-PAYLOAD"
に設定して送信する必要があります。
Python
この例では、署名付きリクエストを安全な接続経由でネットワークに登録されたサービスに送信します。requests
botocore
および awscrt
パッケージをインストールするには、次のコマンドを使用します。詳細については、AWS CRTPython
pip install botocore awscrt
Lambda でクライアントアプリケーションを実行する場合は、Lambda レイヤーawscrt
を使用して をインストールするか、デプロイパッケージに含めます。
次の例では、プレースホルダー値を独自の値に置き換えます。
Java で Intercepter を使用する場合
この例では Amazon Request Signing Interceptor
import com.amazonaws.http.AwsRequestSigningApacheInterceptor; import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import software.amazon.awssdk.auth.signer.Aws4UnsignedPayloadSigner; import software.amazon.awssdk.regions.Region; import java.nio.charset.StandardCharsets; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; public class App { public static void main(String[] args) { var interceptor = new AwsRequestSigningApacheInterceptor( "vpc-lattice-svcs", Aws4UnsignedPayloadSigner.create(), // requires HTTPS DefaultCredentialsProvider.create(), Region.US_WEST_2.id() ); CloseableHttpClient client = HttpClients.custom() .addInterceptorLast(interceptor) .build(); var httpPost = new HttpPost("https://user-02222f67d3a427111.1234abc.vpc-lattice-svcs.us-west-2.on.aws/create"); httpPost.addHeader("content-type", "application/json"); var body = """ { "name": "Jane Doe", "job": "Engineer" } """; httpPost.setEntity(new ByteArrayEntity(body.getBytes(StandardCharsets.UTF_8))); try (var response = client.execute(httpPost)) { System.out.println(new String(response.getEntity().getContent().readAllBytes())); } catch (Exception e) { throw new RuntimeException(e); } } }
Java で Intercepter を使用しない場合
この例は、カスタムインターセプターを使用してリクエスト署名を実行する方法を示しています。AWS SDK for Java 2.x
import java.io.ByteArrayInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.List; import java.util.Map; import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import software.amazon.awssdk.auth.signer.Aws4UnsignedPayloadSigner; import software.amazon.awssdk.auth.signer.AwsSignerExecutionAttribute; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.regions.Region; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; public class App { public static void main(String[] args) { var signer = Aws4UnsignedPayloadSigner.create(); // requires HTTPS Map<String, String> headers = new HashMap<>(); headers.put("content-type", "application/json"); var body = """ { "name": "Jane Doe", "job": "Engineer" } """; String endpoint = "https://user-02222f67d3a427111.1234abc.vpc-lattice-svcs.us-west-2.on.aws/create"; var sdkRequest = SdkHttpFullRequest.builder().method(SdkHttpMethod.POST); sdkRequest.host("user-02222f67d3a427111.1234abc.vpc-lattice-svcs.us-west-2.on.aws"); sdkRequest.protocol("HTTPS"); sdkRequest.encodedPath("/create"); sdkRequest.contentStreamProvider(() -> new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8))); for (Map.Entry<String, String> header : headers.entrySet()) { sdkRequest.putHeader(header.getKey(), header.getValue()); } ExecutionAttributes attributes = ExecutionAttributes.builder() .put(AwsSignerExecutionAttribute.AWS_CREDENTIALS, DefaultCredentialsProvider.create().resolveCredentials()) .put(AwsSignerExecutionAttribute.SERVICE_SIGNING_NAME, "vpc-lattice-svcs") .put(AwsSignerExecutionAttribute.SIGNING_REGION, Region.US_WEST_2) .build(); SdkHttpFullRequest prepRequest = signer.sign(sdkRequest.build(), attributes); HttpPost httpPost = new HttpPost(endpoint); for (Map.Entry<String, List<String>> header : prepRequest.headers().entrySet()) { if (header.getKey().equalsIgnoreCase("host")) { continue; } for(var value : header.getValue()) { httpPost.addHeader(header.getKey(), value); } } CloseableHttpClient client = HttpClients.custom().build(); httpPost.setEntity(new ByteArrayEntity(body.getBytes(StandardCharsets.UTF_8))); try (var response = client.execute(httpPost)){ System.out.println(new String(response.getEntity().getContent().readAllBytes())); } catch (IOException e) { throw new RuntimeException(e); } } }
Node.js
この例では、aws-crt NodeJS バインディング
aws-crt
パッケージをインストールするには、次のコマンドを使用します。
npm -i aws-crt
AWS_REGION
環境変数が存在する場合、この例では AWS_REGION
で指定されたリージョンを使用しています。デフォルトのリージョンは us-east-1
です。
Golang - GRPC
この例ではAWS SDK、Go プログラミング言語の
package main import ( "context" "crypto/tls" "crypto/x509" "flag" "fmt" "log" "net/http" "net/url" "strings" "time" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "github.com/aws/aws-sdk-go-v2/aws" v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" "github.com/aws/aws-sdk-go-v2/config" ecpb "google.golang.org/grpc/examples/features/proto/echo" ) const ( headerContentSha = "x-amz-content-sha256" headerSecurityToken = "x-amz-security-token" headerDate = "x-amz-date" headerAuthorization = "authorization" unsignedPayload = "UNSIGNED-PAYLOAD" ) type SigV4GrpcSigner struct { service string region string credProvider aws.CredentialsProvider signer *v4.Signer } func NewSigV4GrpcSigner(service string, region string, credProvider aws.CredentialsProvider) *SigV4GrpcSigner { signer := v4.NewSigner() return &SigV4GrpcSigner{ service: service, region: region, credProvider: credProvider, signer: signer, } } func (s *SigV4GrpcSigner) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { ri, _ := credentials.RequestInfoFromContext(ctx) creds, err := s.credProvider.Retrieve(ctx) if err != nil { return nil, fmt.Errorf("failed to load credentials: %w", err) } // The URI we get here is scheme://authority/service/ - for siging we want to include the RPC name // But RequestInfoFromContext only has the combined /service/rpc-name - so read the URI, and // replace the Path with what we get from RequestInfo. parsed, err := url.Parse(uri[0]) if err != nil { return nil, err } parsed.Path = ri.Method // Build a request for the signer. bodyReader := strings.NewReader("") req, err := http.NewRequest("POST", uri[0], bodyReader) if err != nil { return nil, err } date := time.Now() req.Header.Set(headerContentSha, unsignedPayload) req.Header.Set(headerDate, date.String()) if creds.SessionToken != "" { req.Header.Set(headerSecurityToken, creds.SessionToken) } // The signer wants this as //authority/path // So get this by triming off the scheme and the colon before the first slash. req.URL.Opaque = strings.TrimPrefix(parsed.String(), parsed.Scheme+":") err = s.signer.SignHTTP(context.Background(), creds, req, unsignedPayload, s.service, s.region, date) if err != nil { return nil, fmt.Errorf("failed to sign request: %w", err) } // Pull the relevant headers out of the signer, and return them to get // included in the request we make. reqHeaders := map[string]string{ headerContentSha: req.Header.Get(headerContentSha), headerDate: req.Header.Get(headerDate), headerAuthorization: req.Header.Get(headerAuthorization), } if req.Header.Get(headerSecurityToken) != "" { reqHeaders[headerSecurityToken] = req.Header.Get(headerSecurityToken) } return reqHeaders, nil } func (c *SigV4GrpcSigner) RequireTransportSecurity() bool { return true } var addr = flag.String("addr", "some-lattice-service:443", "the address to connect to") var region = flag.String("region", "us-west-2", "region") func callUnaryEcho(client ecpb.EchoClient, message string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() resp, err := client.UnaryEcho(ctx, &ecpb.EchoRequest{Message: message}) if err != nil { log.Fatalf("client.UnaryEcho(_) = _, %v: ", err) } fmt.Println("UnaryEcho: ", resp.Message) } func main() { flag.Parse() cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithClientLogMode(aws.LogSigning)) if err != nil { log.Fatalf("failed to load SDK configuration, %v", err) } pool, _ := x509.SystemCertPool() tlsConfig := &tls.Config{ RootCAs: pool, } authority, _, _ := strings.Cut(*addr, ":") // Remove the port from the addr opts := []grpc.DialOption{ grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)), // Lattice needs both the Authority to be set (without a port), and the SigV4 signer grpc.WithAuthority(authority), grpc.WithPerRPCCredentials(NewSigV4GrpcSigner("vpc-lattice-svcs", *region, cfg.Credentials)), } conn, err := grpc.Dial(*addr, opts...) if err != nil { log.Fatalf("did not connect: %v", err) } defer conn.Close() rgc := ecpb.NewEchoClient(conn) callUnaryEcho(rgc, "hello world") }