CodeSampleX

サンプル

aws4 1.13.2: sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign

検証済みサンプル — npm aws4 1.13.2: sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign. node 22 · linux alpine/x64 · docker で contract…

sha256:8f8ba492115e5ad229fe51119e4d4882ddb4405af0d88c7720ad4cfc4d2526ab

このネットワークが提供するのは一つだけです。ビルドされるサンプル。サンドボックスで実行し、署名済みの受領証を保管します。等級はつけず、何も保証しません — 同じコードがあなたの環境でビルドされるかは測定していません。 合格した契約受領証を提出した異なる署名鍵の数です。1 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。 MIT-0

実行証拠

宣言された環境と署名済みの実行を分けてあります。このサンプルが何をどこで実行したかをそのまま確認できます。

証拠の基準
署名済みコントラクト合格
検証レシート
1
ビルドした署名鍵
1
宣言された環境 linux 24 · ubuntu · glibc 2.39 x64 npm

検証実行環境

環境 コントラクト ステージ 実行日
node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5…
2026-08-27

ケース

HOW
ゴール
sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign
パッケージ
シンボル
  • aws4.sign
作成日
2026-08-27T20:26:37Z

コントラクト

  1. assert aws4.sign populates Authorization, X-Amz-Date, and Host headers on HTTP request options
  2. assert Authorization header follows AWS4-HMAC-SHA256 format containing Credential, SignedHeaders, and Signature
  3. assert aws4.sign sets Content-Type and Content-Length headers for POST requests with body content
  4. assert aws4.sign adds X-Amz-Security-Token header and includes it in signed headers when sessionToken is provided
  5. assert aws4.sign computes SHA256 payload hash and sets X-Amz-Content-Sha256 header for S3 service requests
  6. assert aws4.sign with signQuery option embeds SigV4 parameters into query string without Authorization header
  7. assert aws4.RequestSigner resolves service name and AWS region automatically from amazonaws.com hostnames
  8. assert aws4.RequestSigner exposes canonicalString, stringToSign, and signature generation methods

ファイル

  • PROMPT.md
  • csx.json
  • package-lock.json
  • package.json
  • spec.json
  • src/index.js
  • test/contract.mjs

ソースアーティファクトをダウンロード (tar.gz)

ソース

PROMPT.md
Clean-room public code sample — generation instructions

Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.

A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.

Goal: sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign
Kind: HOW

Use EXACTLY these public packages and versions:
  - pkg:npm/aws4@1.13.2
Demonstrate these symbols/APIs:
  - aws4.sign

Rules:
  - One focused purpose; the smallest project that proves the goal.
  - Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
  - Pin every dependency with a lockfile so resolution is reproducible.
  - No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
  - No personal names, emails, company names, or project identifiers of any kind.
  - No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
  - Keep it under 200 files and 256KB packed.
csx.json
{"case":{"caseId":"case:sha256:2ae9008937e9bf62e34a804a0c03d8e3db4181d04855e3b1952c2f4370e6d4af","contract":["assert aws4.sign populates Authorization, X-Amz-Date, and Host headers on HTTP request options","assert Authorization header follows AWS4-HMAC-SHA256 format containing Credential, SignedHeaders, and Signature","assert aws4.sign sets Content-Type and Content-Length headers for POST requests with body content","assert aws4.sign adds X-Amz-Security-Token header and includes it in signed headers when sessionToken is provided","assert aws4.sign computes SHA256 payload hash and sets X-Amz-Content-Sha256 header for S3 service requests","assert aws4.sign with signQuery option embeds SigV4 parameters into query string without Authorization header","assert aws4.RequestSigner resolves service name and AWS region automatically from amazonaws.com hostnames","assert aws4.RequestSigner exposes canonicalString, stringToSign, and signature generation methods"],"goal":"sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign","kind":"HOW","packages":["pkg:npm/aws4@1.13.2"],"schemaVersion":1,"symbols":["aws4.sign"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","libc":"glibc","libcVersion":"2.39","os":"linux","osVersionBucket":"24","packageManager":"npm","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/aws4@1.13.2"],"schemaVersion":1,"subject":"pkg:npm/aws4@1.13.2","symbols":["aws4.sign"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "sample-aws4",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "sample-aws4",
      "version": "1.0.0",
      "license": "MIT-0",
      "dependencies": {
        "aws4": "1.13.2"
      }
    },
    "node_modules/aws4": {
      "version": "1.13.2",
      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
      "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==",
      "license": "MIT"
    }
  }
}
package.json
{
  "name": "sample-aws4",
  "version": "1.0.0",
  "private": true,
  "description": "Clean-room verification of pkg:npm/aws4@1.13.2",
  "main": "src/index.js",
  "license": "MIT-0",
  "dependencies": {
    "aws4": "1.13.2"
  }
}
spec.json
{
  "schemaVersion": 1,
  "goal": "sign an HTTP request with AWS Signature Version 4 credentials using aws4.sign",
  "kind": "HOW",
  "packages": [
    "pkg:npm/aws4@1.13.2"
  ],
  "symbols": [
    "aws4.sign"
  ]
}
src/index.js
'use strict';

const aws4 = require('aws4');

/**
 * Signs an HTTP request options object with AWS Signature Version 4 credentials.
 * Modifies and returns the request options with Authorization and X-Amz-Date headers.
 *
 * @param {object} request - Request options (host/hostname, path, method, headers, body, service, region).
 * @param {object} [credentials] - AWS credentials { accessKeyId, secretAccessKey, sessionToken }.
 * @returns {object} Signed request object.
 */
function signRequest(request, credentials) {
  return aws4.sign(request, credentials);
}

/**
 * Signs an HTTP request using query parameters instead of Authorization header.
 * Useful for generating pre-signed URLs.
 *
 * @param {object} request - Request options.
 * @param {object} [credentials] - AWS credentials.
 * @returns {object} Signed request object with query parameters populated on path.
 */
function signQuery(request, credentials) {
  const req = Object.assign({}, request, { signQuery: true });
  return aws4.sign(req, credentials);
}

/**
 * Signs an HTTP request using temporary STS credentials (including session token).
 * Populates X-Amz-Security-Token header.
 *
 * @param {object} request - Request options.
 * @param {object} credentials - AWS credentials containing sessionToken.
 * @returns {object} Signed request object.
 */
function signWithSessionToken(request, credentials) {
  return aws4.sign(request, credentials);
}

/**
 * Signs an S3 request with automatic SHA256 payload calculation.
 *
 * @param {object} request - Request options for S3 service.
 * @param {object} [credentials] - AWS credentials.
 * @returns {object} Signed request object with X-Amz-Content-Sha256 header.
 */
function signS3Request(request, credentials) {
  const req = Object.assign({ service: 's3' }, request);
  return aws4.sign(req, credentials);
}

/**
 * Creates a RequestSigner instance for custom inspection and step-by-step signing.
 *
 * @param {object|string} request - Request options or URL string.
 * @param {object} [credentials] - AWS credentials.
 * @returns {aws4.RequestSigner} RequestSigner instance.
 */
function createRequestSigner(request, credentials) {
  return new aws4.RequestSigner(request, credentials);
}

module.exports = {
  signRequest,
  signQuery,
  signWithSessionToken,
  signS3Request,
  createRequestSigner,
  aws4,
};
test/contract.mjs
import assert from 'node:assert';
import crypto from 'node:crypto';
import { createRequire } from 'node:module';

const require = createRequire(import.meta.url);
const aws4 = require('aws4');
const {
  signRequest,
  signQuery,
  signWithSessionToken,
  signS3Request,
  createRequestSigner,
} = require('../src/index.js');

const dummyCredentials = {
  accessKeyId: 'mock-access-key-id',
  secretAccessKey: 'mock-secret-access-key',
};

async function runContract() {
  // 1. assert aws4.sign populates Authorization, X-Amz-Date, and Host headers on HTTP request options
  const req1 = {
    host: 'sqs.us-east-1.amazonaws.com',
    path: '/?Action=ListQueues&Version=2012-11-05',
    service: 'sqs',
    region: 'us-east-1',
    headers: {
      'Date': 'Mon, 09 Sep 2024 00:00:00 GMT',
    },
  };
  const signed1 = signRequest(req1, dummyCredentials);
  assert.ok(signed1.headers.Authorization, 'Authorization header should be set');
  assert.strictEqual(signed1.headers['X-Amz-Date'], '20240909T000000Z', 'X-Amz-Date should match ISO-like format');
  assert.strictEqual(signed1.headers.Host, 'sqs.us-east-1.amazonaws.com', 'Host header should be set');

  // 2. assert Authorization header follows AWS4-HMAC-SHA256 format containing Credential, SignedHeaders, and Signature
  const authHeader = signed1.headers.Authorization;
  assert.ok(
    authHeader.startsWith('AWS4-HMAC-SHA256 Credential=mock-access-key-id/20240909/us-east-1/sqs/aws4_request'),
    'Authorization must start with AWS4-HMAC-SHA256 and expected Credential scope'
  );
  assert.ok(authHeader.includes('SignedHeaders='), 'Authorization must contain SignedHeaders');
  assert.ok(authHeader.includes('Signature='), 'Authorization must contain Signature');
  const sigMatch = authHeader.match(/Signature=([a-f0-9]{64})/);
  assert.ok(sigMatch && sigMatch[1].length === 64, 'Signature must be a 64-character hexadecimal string');

  // 3. assert aws4.sign sets Content-Type and Content-Length headers for POST requests with body content
  const postReq = {
    host: 'dynamodb.us-east-1.amazonaws.com',
    path: '/',
    method: 'POST',
    body: '{"TableName":"TestTable"}',
  };
  const signedPost = signRequest(postReq, dummyCredentials);
  assert.strictEqual(
    signedPost.headers['Content-Type'],
    'application/x-www-form-urlencoded; charset=utf-8',
    'Default Content-Type should be set for POST requests with body'
  );
  assert.strictEqual(
    signedPost.headers['Content-Length'],
    25,
    'Content-Length must match byte length of payload'
  );

  // 4. assert aws4.sign adds X-Amz-Security-Token header and includes it in signed headers when sessionToken is provided
  const stsCredentials = {
    ...dummyCredentials,
    sessionToken: 'mock-session-token',
  };
  const stsReq = {
    host: 'sqs.us-east-1.amazonaws.com',
    path: '/',
  };
  const signedSts = signWithSessionToken(stsReq, stsCredentials);
  assert.strictEqual(
    signedSts.headers['X-Amz-Security-Token'],
    'mock-session-token',
    'X-Amz-Security-Token header should match session token'
  );
  assert.ok(
    signedSts.headers.Authorization.toLowerCase().includes('x-amz-security-token'),
    'Authorization SignedHeaders must include x-amz-security-token'
  );

  // 5. assert aws4.sign computes SHA256 payload hash and sets X-Amz-Content-Sha256 header for S3 service requests
  const s3Payload = 'Sample payload for S3 upload';
  const expectedS3Hash = crypto.createHash('sha256').update(s3Payload).digest('hex');
  const s3Req = {
    host: 'example-bucket.s3.amazonaws.com',
    path: '/data.txt',
    method: 'PUT',
    body: s3Payload,
  };
  const signedS3 = signS3Request(s3Req, dummyCredentials);
  assert.strictEqual(
    signedS3.headers['X-Amz-Content-Sha256'],
    expectedS3Hash,
    'X-Amz-Content-Sha256 header must match SHA256 of the body'
  );

  // 6. assert aws4.sign with signQuery option embeds SigV4 parameters into query string without Authorization header
  const queryReq = {
    host: 'example-bucket.s3.amazonaws.com',
    path: '/data.txt',
    service: 's3',
    region: 'us-east-1',
  };
  const signedQuery = signQuery(queryReq, dummyCredentials);
  assert.strictEqual(signedQuery.headers.Authorization, undefined, 'Authorization header must not be set when signQuery is true');
  assert.ok(signedQuery.path.includes('X-Amz-Algorithm=AWS4-HMAC-SHA256'), 'Path must contain X-Amz-Algorithm query param');
  assert.ok(signedQuery.path.includes('X-Amz-Credential='), 'Path must contain X-Amz-Credential query param');
  assert.ok(signedQuery.path.includes('X-Amz-Date='), 'Path must contain X-Amz-Date query param');
  assert.ok(signedQuery.path.includes('X-Amz-SignedHeaders='), 'Path must contain X-Amz-SignedHeaders query param');
  assert.ok(signedQuery.path.includes('X-Amz-Signature='), 'Path must contain X-Amz-Signature query param');

  // 7. assert aws4.RequestSigner resolves service name and AWS region automatically from amazonaws.com hostnames
  const signer = createRequestSigner({
    host: 'dynamodb.eu-central-1.amazonaws.com',
    path: '/',
  }, dummyCredentials);
  assert.strictEqual(signer.service, 'dynamodb', 'Service should be inferred as dynamodb from host');
  assert.strictEqual(signer.region, 'eu-central-1', 'Region should be inferred as eu-central-1 from host');

  // 8. assert aws4.RequestSigner exposes canonicalString, stringToSign, and signature generation methods
  assert.strictEqual(typeof signer.canonicalString, 'function', 'canonicalString method should exist');
  assert.strictEqual(typeof signer.stringToSign, 'function', 'stringToSign method should exist');
  assert.strictEqual(typeof signer.signature, 'function', 'signature method should exist');
  assert.strictEqual(typeof signer.authHeader, 'function', 'authHeader method should exist');

  const canonical = signer.canonicalString();
  assert.ok(canonical.startsWith('GET\n/'), 'Canonical request string should start with method and path');
  const stringToSign = signer.stringToSign();
  assert.ok(stringToSign.startsWith('AWS4-HMAC-SHA256\n'), 'String to sign must start with AWS4-HMAC-SHA256');
  const signatureHex = signer.signature();
  assert.strictEqual(typeof signatureHex, 'string');
  assert.strictEqual(signatureHex.length, 64, 'Signature must be 64 characters hex');

  console.log('Contract tests passed successfully.');
}

runContract().catch((err) => {
  console.error('Contract test failed:', err);
  process.exit(1);
});

オリジンシーダー

匿名