Skip to content

Commit

Permalink
[SRA] Rules-based authentication resolvers (#3540)
Browse files Browse the repository at this point in the history
  • Loading branch information
dscpinheiro authored Nov 6, 2024
1 parent d61788b commit 680c9eb
Show file tree
Hide file tree
Showing 11 changed files with 295 additions and 56 deletions.
16 changes: 3 additions & 13 deletions generator/ServiceClientGeneratorLib/GeneratorDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,6 @@ public class GeneratorDriver

private static ConcurrentBag<string> codeGeneratedServiceNames = new ConcurrentBag<string>();

/// <summary>
/// Collection of services for which modeled auth resolvers (i.e. using information from their model files) should be generated.
/// </summary>
/// <remarks>
/// This is an allow-list for now (to prevent creating >400 files), but will be updated to a deny-list in the future (only a handful
/// of services such as S3 and EventBridge won't use modeled auth resolvers).
/// </remarks>
private static readonly HashSet<string> _allowListModeledAuthResolvers = new HashSet<string>
{
"AutoScaling",
};

public GeneratorDriver(ServiceConfiguration config, GenerationManifest generationManifest, GeneratorOptions options)
{
FilesWrittenToGeneratorFolder = new HashSet<string>();
Expand Down Expand Up @@ -209,7 +197,9 @@ public void Execute()
ExecuteTestGenerator(new EndpointProviderTests(), Configuration.ClassName + "EndpointProviderTests.cs", "Endpoints");
}

if (_allowListModeledAuthResolvers.Contains(Configuration.ClassName))
// TODO: We'll eventually generate auth resolvers for all services, but only including a couple for now to keep
// the number of generated changes low.
if (Configuration.ClassName == "AutoScaling" || Configuration.ClassName == "S3")
{
ExecuteGenerator(new ModeledResolver(), "Amazon" + Configuration.ClassName + "AuthResolver.cs", "Internal");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,37 +79,96 @@ public override string TransformText()

#line default
#line hidden
this.Write("AuthSchemeHandler : BaseAuthResolverHandler\r\n {\r\n /// <summary>\r\n " +
" /// Auth scheme resolver for AutoScaling.\r\n /// </summary>\r\n pub" +
"lic Amazon");
this.Write("AuthSchemeHandler : BaseAuthResolverHandler\r\n {\r\n");

#line 38 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
if (IsServiceAllowListedForRulesBasedResolver()) {

#line default
#line hidden
this.Write(" private readonly Amazon");

#line 39 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(this.Config.ClassName));

#line default
#line hidden
this.Write("EndpointResolver _endpointResolver = new();\r\n\r\n");

#line 41 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
}

#line default
#line hidden
this.Write(" /// <summary>\r\n /// Modeled auth scheme resolver for ");

#line 43 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(this.Config.ClassName));

#line default
#line hidden
this.Write(".\r\n /// </summary>\r\n public Amazon");

#line 45 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(this.Config.ClassName));

#line default
#line hidden
this.Write("AuthSchemeResolver AuthSchemeResolver { get; } = new();\r\n\r\n /// <inheritdo" +
"c/>\r\n protected override List<IAuthSchemeOption> ResolveAuthOptions(IRequ" +
"estContext requestContext)\r\n {\r\n var mappedParameters = new Am" +
"azon");
"c/>\r\n protected override List<IAuthSchemeOption> ResolveAuthOptions(IExec" +
"utionContext executionContext)\r\n {\r\n");

#line 50 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
if (IsServiceAllowListedForRulesBasedResolver()) {

#line 46 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line default
#line hidden
this.Write(" // Since ");

#line 51 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(this.Config.ClassName));

#line default
#line hidden
this.Write(@" includes auth schemes in its endpoint rules, we'll attempt to delegate resolution to the endpoint
// resolver first (falling back to the modeled resolver if no options are returned).
var endpoint = _endpointResolver.GetEndpoint(executionContext);
// This means the endpoints resolver is executed twice intentionally (at this point and then later in the pipeline
// to determine which endpoint the SDK should use for the request).
var endpointAuthSchemes = RetrieveSchemesFromEndpoint(endpoint);
if (endpointAuthSchemes != null)
{
return endpointAuthSchemes;
}
");

#line 63 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
}

#line default
#line hidden
this.Write(" var requestContext = executionContext.RequestContext;\r\n va" +
"r mappedParameters = new Amazon");

#line 65 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(this.Config.ClassName));

#line default
#line hidden
this.Write("AuthSchemeParameters\r\n {\r\n Operation = requestContext.R" +
"equest.RequestName,\r\n");

#line 49 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 68 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
if (IsSigV4Supported()) {

#line default
#line hidden
this.Write(" Region = requestContext.ClientConfig.RegionEndpoint?.SystemName,\r" +
"\n");

#line 51 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 70 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
}

#line default
Expand All @@ -118,136 +177,136 @@ public override string TransformText()
"arameters);\r\n }\r\n }\r\n\r\n /// <inheritdoc cref=\"IAuthSchemeResolver{T" +
"}\" />\r\n public class Amazon");

#line 59 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 78 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(this.Config.ClassName));

#line default
#line hidden
this.Write("AuthSchemeResolver : IAuthSchemeResolver<Amazon");

#line 59 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 78 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(this.Config.ClassName));

#line default
#line hidden
this.Write("AuthSchemeParameters>\r\n {\r\n /// <inheritdoc />\r\n public List<IAu" +
"thSchemeOption> ResolveAuthScheme(Amazon");

#line 62 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 81 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(this.Config.ClassName));

#line default
#line hidden
this.Write("AuthSchemeParameters authParameters)\r\n {\r\n switch (authParamete" +
"rs.Operation)\r\n {\r\n");

#line 66 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 85 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
foreach (var operation in GetOperationsWithAuthSchemes()) {

#line default
#line hidden
this.Write("\t\t\t\tcase \"");

#line 67 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 86 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(operation.Name));

#line default
#line hidden
this.Write("Request\":\r\n");

#line 68 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 87 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
if (IsKnownSchemeList(operation.AuthSchemes, out string operationSchemesContent)) {

#line default
#line hidden
this.Write(" return ");

#line 69 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 88 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(operationSchemesContent));

#line default
#line hidden
this.Write(";\r\n");

#line 70 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 89 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
} else {

#line default
#line hidden
this.Write(" return new List<IAuthSchemeOption> \r\n {\r\n");

#line 73 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 92 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
foreach (var operationScheme in operation.AuthSchemes) {

#line default
#line hidden
this.Write(" new AuthSchemeOption { SchemeId = \"");

#line 74 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 93 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(operationScheme));

#line default
#line hidden
this.Write("\" },\r\n");

#line 75 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 94 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
}

#line default
#line hidden
this.Write(" };\r\n");

#line 77 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 96 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
}}

#line default
#line hidden
this.Write(" default:\r\n // Default for the service, applies" +
" to all remaining operations.\r\n");

#line 80 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 99 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
if (IsKnownSchemeList(GetServiceAuthSchemes(), out string serviceSchemesContent)) {

#line default
#line hidden
this.Write(" return ");

#line 81 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 100 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(serviceSchemesContent));

#line default
#line hidden
this.Write(";\r\n");

#line 82 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 101 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
} else {

#line default
#line hidden
this.Write(" return new List<IAuthSchemeOption> \r\n {\r\n");

#line 85 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 104 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
foreach (var serviceScheme in GetServiceAuthSchemes()) {

#line default
#line hidden
this.Write(" \t\t new AuthSchemeOption { SchemeId = \"");

#line 86 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 105 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(serviceScheme));

#line default
#line hidden
this.Write("\" },\r\n");

#line 87 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 106 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
}

#line default
#line hidden
this.Write(" };\r\n");

#line 89 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
#line 108 "C:\Projects\aws-sdk-net-v4\generator\ServiceClientGeneratorLib\Generators\AuthResolvers\ModeledResolver.tt"
}

#line default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ namespace ServiceClientGenerator.Generators.AuthResolvers
{
public partial class ModeledResolver
{
private readonly HashSet<string> _allowListedServices = new HashSet<string>
{
"S3",
"EventBridge",
"SimpleEmailServiceV2",
"CloudFrontKeyValueStore",
};

/// <summary>
/// Returns whether the generated resolver should delegate auth scheme resolution to the endpoints resolver.
/// </summary>
private bool IsServiceAllowListedForRulesBasedResolver() =>
_allowListedServices.Contains(Config.ClassName);

/// <summary>
/// Returns whether this service supports SigV4 (and therefore should include region in its auth scheme parameters).
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,33 @@ namespace <#=this.Config.Namespace#>.Internal
/// </summary>
public class Amazon<#=this.Config.ClassName#>AuthSchemeHandler : BaseAuthResolverHandler
{
<# if (IsServiceAllowListedForRulesBasedResolver()) { #>
private readonly Amazon<#=this.Config.ClassName#>EndpointResolver _endpointResolver = new();

<# } #>
/// <summary>
/// Auth scheme resolver for AutoScaling.
/// Modeled auth scheme resolver for <#=this.Config.ClassName#>.
/// </summary>
public Amazon<#=this.Config.ClassName#>AuthSchemeResolver AuthSchemeResolver { get; } = new();

/// <inheritdoc/>
protected override List<IAuthSchemeOption> ResolveAuthOptions(IRequestContext requestContext)
protected override List<IAuthSchemeOption> ResolveAuthOptions(IExecutionContext executionContext)
{
<# if (IsServiceAllowListedForRulesBasedResolver()) { #>
// Since <#=this.Config.ClassName#> includes auth schemes in its endpoint rules, we'll attempt to delegate resolution to the endpoint
// resolver first (falling back to the modeled resolver if no options are returned).
var endpoint = _endpointResolver.GetEndpoint(executionContext);

// This means the endpoints resolver is executed twice intentionally (at this point and then later in the pipeline
// to determine which endpoint the SDK should use for the request).
var endpointAuthSchemes = RetrieveSchemesFromEndpoint(endpoint);
if (endpointAuthSchemes != null)
{
return endpointAuthSchemes;
}

<# } #>
var requestContext = executionContext.RequestContext;
var mappedParameters = new Amazon<#=this.Config.ClassName#>AuthSchemeParameters
{
Operation = requestContext.Request.RequestName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace Amazon.Runtime.Credentials.Internal
public class AnonymousAuthScheme : IAuthScheme<AnonymousAWSCredentials>
{
/// <inheritdoc/>
public string SchemeId => "smithy.api#noAuth";
public string SchemeId => AuthSchemeOption.NoAuth;

/// <inheritdoc/>
public IIdentityResolver GetIdentityResolver(IIdentityResolverConfiguration configuration)
Expand Down
Loading

0 comments on commit 680c9eb

Please sign in to comment.