Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(experimentalIdentityAndAuth): Add generic @aws.auth#sigv4 support #885

Merged
merged 3 commits into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/shaggy-adults-yawn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@smithy/experimental-identity-and-auth": patch
---

INTERNAL USE ONLY: Add `@aws.auth#sigv4` interfaces and classes
1 change: 1 addition & 0 deletions packages/experimental-identity-and-auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"license": "Apache-2.0",
"dependencies": {
"@smithy/protocol-http": "workspace:^",
"@smithy/signature-v4": "workspace:^",
"@smithy/types": "workspace:^",
"tslib": "^2.5.0"
},
Expand Down
33 changes: 33 additions & 0 deletions packages/experimental-identity-and-auth/src/SigV4Signer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { HttpRequest } from "@smithy/protocol-http";
import { SignatureV4 } from "@smithy/signature-v4";
import { AwsCredentialIdentity, HttpRequest as IHttpRequest } from "@smithy/types";

import { HttpSigner } from "./HttpSigner";

/**
* @internal
*/
export class SigV4Signer implements HttpSigner {
async sign(
httpRequest: HttpRequest,
identity: AwsCredentialIdentity,
signingProperties: Record<string, any>
): Promise<IHttpRequest> {
const clonedRequest = httpRequest.clone();
const signer = new SignatureV4({
applyChecksum: signingProperties.applyChecksum !== undefined ? signingProperties.applyChecksum : true,
credentials: identity,
region: signingProperties.region,
service: signingProperties.name,
sha256: signingProperties.sha256,
uriEscapePath: signingProperties.uriEscapePath !== undefined ? signingProperties.uriEscapePath : true,
});
return signer.sign(clonedRequest, {
signingDate: new Date(),
signableHeaders: signingProperties.signableHeaders,
unsignableHeaders: signingProperties.unsignableHeaders,
signingRegion: signingProperties.signingRegion,
signingService: signingProperties.signingService,
});
}
}
3 changes: 2 additions & 1 deletion packages/experimental-identity-and-auth/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
export * from "./IdentityProviderConfiguration";
export * from "./HttpAuthScheme";
export * from "./HttpSigner";
export * from "./noAuth";
export * from "./SigV4Signer";
export * from "./apiKeyIdentity";
export * from "./httpApiKeyAuth";
export * from "./httpBearerAuth";
export * from "./noAuth";
export * from "./tokenIdentity";
19 changes: 13 additions & 6 deletions smithy-typescript-codegen-test/model/main.smithy
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ use smithy.waiters#waitable

/// Provides weather forecasts.
@fakeProtocol
// feat(experimentalIdentityAndAuth): uncomment operations as individual
// auth scheme support is implemented
@httpApiKeyAuth(name: "X-Api-Key", in: "header")
@httpBearerAuth
// @sigv4(name: "weather")
// @auth([sigv4])
@sigv4(name: "weather")
@auth([sigv4])
@paginated(inputToken: "nextToken", outputToken: "nextToken", pageSize: "pageSize")
service Weather {
version: "2006-03-01"
Expand All @@ -23,15 +21,15 @@ service Weather {
GetCurrentTime
// util-stream.integ.spec.ts
Invoke
// feat(experimentalIdentityAndAuth): uncomment operations as individual
// auth scheme support is implemented
// experimentalIdentityAndAuth
OnlyHttpApiKeyAuth
OnlyHttpApiKeyAuthOptional
OnlyHttpBearerAuth
OnlyHttpBearerAuthOptional
OnlyHttpApiKeyAndBearerAuth
OnlyHttpApiKeyAndBearerAuthReversed
OnlySigv4Auth
OnlySigv4AuthOptional
SameAsService
]
}
Expand All @@ -44,6 +42,10 @@ operation OnlyHttpApiKeyAuth {}
@auth([httpBearerAuth])
operation OnlyHttpBearerAuth {}

@http(method: "GET", uri: "/OnlySigv4Auth")
@auth([sigv4])
operation OnlySigv4Auth {}

@http(method: "GET", uri: "/OnlyHttpApiKeyAndBearerAuth")
@auth([httpApiKeyAuth, httpBearerAuth])
operation OnlyHttpApiKeyAndBearerAuth {}
Expand All @@ -62,6 +64,11 @@ operation OnlyHttpApiKeyAuthOptional {}
@optionalAuth
operation OnlyHttpBearerAuthOptional {}

@http(method: "GET", uri: "/OnlySigv4AuthOptional")
@auth([sigv4])
@optionalAuth
operation OnlySigv4AuthOptional {}

@http(method: "GET", uri: "/SameAsService")
operation SameAsService {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ public enum TypeScriptDependency implements Dependency {
AWS_SDK_NODE_HTTP_HANDLER("dependencies", "@smithy/node-http-handler", "^2.0.5", false),

// Conditionally added when setting the auth middleware.
AWS_SDK_UTIL_MIDDLEWARE("dependencies", "@smithy/util-middleware", "^2.0.0", false),
UTIL_MIDDLEWARE("dependencies", "@smithy/util-middleware", "^2.0.0", false),
@Deprecated AWS_SDK_UTIL_MIDDLEWARE("dependencies", "@smithy/util-middleware", "^2.0.0", false),

// Conditionally added if a event stream shape is found anywhere in the model
AWS_SDK_EVENTSTREAM_SERDE_CONFIG_RESOLVER(
Expand All @@ -114,6 +115,9 @@ public enum TypeScriptDependency implements Dependency {
@Deprecated UTIL_STREAM_BROWSER("dependencies", "@smithy/util-stream-browser", "^2.0.5", false),
UTIL_STREAM("dependencies", "@smithy/util-stream", "^2.0.5", false),

// Conditionally added when @aws.auth#sigv4 is used
SIGNATURE_V4("dependencies", "@smithy/signature-v4", "^2.0.4", false),

// feat(experimentalIdentityAndAuth): Conditionally added dependencies for `experimentalIdentityAndAuth`.
// This package should never have a major version, and should only use minor and patch versions in development.
EXPERIMENTAL_IDENTITY_AND_AUTH("dependencies", "@smithy/experimental-identity-and-auth", "~0.0.1", false),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.typescript.codegen.auth.http.integration;

import java.util.Optional;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.typescript.codegen.ApplicationProtocol;
import software.amazon.smithy.typescript.codegen.ConfigField;
import software.amazon.smithy.typescript.codegen.LanguageTarget;
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthOptionProperty;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthOptionProperty.Type;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthScheme;
import software.amazon.smithy.typescript.codegen.auth.http.HttpAuthSchemeParameter;
import software.amazon.smithy.utils.SmithyInternalApi;

/**
* Support for generic @aws.auth#sigv4.
*
* This is the experimental behavior for `experimentalIdentityAndAuth`.
*/
@SmithyInternalApi
public final class AddSigV4AuthPlugin implements HttpAuthTypeScriptIntegration {

/**
* Integration should only be used if `experimentalIdentityAndAuth` flag is true.
*/
@Override
public boolean matchesSettings(TypeScriptSettings settings) {
return settings.getExperimentalIdentityAndAuth();
}

@Override
public Optional<HttpAuthScheme> getHttpAuthScheme() {
return Optional.of(HttpAuthScheme.builder()
.schemeId(ShapeId.from("aws.auth#sigv4"))
.applicationProtocol(ApplicationProtocol.createDefaultHttpApplicationProtocol())
.putDefaultIdentityProvider(LanguageTarget.SHARED, w -> {
w.write("async () => { throw new Error(\"`credentials` is missing\"); }");
})
.putDefaultSigner(LanguageTarget.SHARED, w -> {
w.addDependency(TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.addImport("SigV4Signer", null,
TypeScriptDependency.EXPERIMENTAL_IDENTITY_AND_AUTH);
w.write("new SigV4Signer()");
})
.addConfigField(new ConfigField("region", w -> {
w.addDependency(TypeScriptDependency.SMITHY_TYPES);
w.addImport("Provider", "__Provider", TypeScriptDependency.SMITHY_TYPES);
w.write("string | __Provider<string>");
}, w -> w.write("The AWS region to which this client will send requests.")))
.addConfigField(new ConfigField("credentials", w -> {
w.addDependency(TypeScriptDependency.SMITHY_TYPES);
w.addImport("AwsCredentialIdentity", null, TypeScriptDependency.SMITHY_TYPES);
w.addImport("AwsCredentialIdentityProvider", null, TypeScriptDependency.SMITHY_TYPES);
w.write("AwsCredentialIdentity | AwsCredentialIdentityProvider");
}, w -> w.write("The credentials used to sign requests.")))
.addHttpAuthSchemeParameter(new HttpAuthSchemeParameter(
"region", w -> w.write("string"), w -> {
w.addDependency(TypeScriptDependency.UTIL_MIDDLEWARE);
w.addImport("normalizeProvider", null, TypeScriptDependency.UTIL_MIDDLEWARE);
w.openBlock("await normalizeProvider(config.region)() || (() => {", "})()", () -> {
w.write("throw new Error(\"expected `region` to be configured for `aws.auth#sigv4`\");");
});
}))
.addHttpAuthOptionProperty(new HttpAuthOptionProperty(
"name", Type.SIGNING, t -> w -> {
w.write("$S", t.toNode().expectObjectNode().getMember("name"));
}))
.addHttpAuthOptionProperty(new HttpAuthOptionProperty(
"region", Type.SIGNING, t -> w -> {
w.write("authParameters.region");
}))
.build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ software.amazon.smithy.typescript.codegen.integration.AddDefaultsModeDependency
software.amazon.smithy.typescript.codegen.auth.http.integration.AddNoAuthPlugin
software.amazon.smithy.typescript.codegen.auth.http.integration.AddHttpApiKeyAuthPlugin
software.amazon.smithy.typescript.codegen.auth.http.integration.AddHttpBearerAuthPlugin
software.amazon.smithy.typescript.codegen.auth.http.integration.AddSigV4AuthPlugin
software.amazon.smithy.typescript.codegen.integration.AddHttpApiKeyAuthPlugin
software.amazon.smithy.typescript.codegen.integration.AddBaseServiceExceptionClass
software.amazon.smithy.typescript.codegen.integration.AddSdkStreamMixinDependency
Expand Down
3 changes: 2 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1890,6 +1890,7 @@ __metadata:
resolution: "@smithy/experimental-identity-and-auth@workspace:packages/experimental-identity-and-auth"
dependencies:
"@smithy/protocol-http": "workspace:^"
"@smithy/signature-v4": "workspace:^"
"@smithy/types": "workspace:^"
"@tsconfig/recommended": 1.0.1
concurrently: 7.0.0
Expand Down Expand Up @@ -2330,7 +2331,7 @@ __metadata:
languageName: unknown
linkType: soft

"@smithy/signature-v4@workspace:packages/signature-v4":
"@smithy/signature-v4@workspace:^, @smithy/signature-v4@workspace:packages/signature-v4":
version: 0.0.0-use.local
resolution: "@smithy/signature-v4@workspace:packages/signature-v4"
dependencies:
Expand Down