Renames for consistency with updated terminology (#123)

Much of the existing code refers to 'entitlements' as properties of the token, or attributes which a token gives permission to.

We've agreed to redefine an 'entitlement' as something which is granted upon an API request. The token is used to obtain the entitlement, but the token is not the entitlement.

This updates the code to better reflect that way of thinking.
This commit is contained in:
peterbom 2018-11-30 08:44:32 +13:00 коммит произвёл Bevan Arps
Родитель ee8e5bb72e
Коммит 0b03b30d82
24 изменённых файлов: 504 добавлений и 505 удалений

Просмотреть файл

@ -19,8 +19,8 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Server.Controllers
private readonly ILogger _logger;
private readonly IApplicationLifetime _lifetime;
// Verifier used to check entitlement
private readonly EntitlementVerifier _verifier;
// Verifier used to check token
private readonly TokenVerifier _verifier;
private const string ApiVersion201705 = "2017-05-01.5.0";
private const string ApiVersion201709 = "2017-09-01.6.0";
@ -37,7 +37,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Server.Controllers
ServerOptions serverOptions,
ILogger logger,
IApplicationLifetime lifetime,
EntitlementVerifier verifier)
TokenVerifier verifier)
{
_serverOptions = serverOptions;
_logger = logger;
@ -77,8 +77,8 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Server.Controllers
"Selected api-version is {ApiVersion}",
apiVersion);
return ExtractParameters(apiVersion, HttpContext, entitlementRequestBody).Match(
whenSuccessful: r => IssueEntitlement(r.Request, r.Token, apiVersion),
return ExtractApprovalRequestParameters(HttpContext, entitlementRequestBody).Match(
whenSuccessful: r => CreateApprovalResponse(r.Request, r.Token, apiVersion),
whenFailure: errors => CreateBadRequestResponse(errors));
}
finally
@ -90,72 +90,72 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Server.Controllers
}
}
private IActionResult IssueEntitlement(EntitlementVerificationRequest request, string token, string apiVersion)
private IActionResult CreateApprovalResponse(TokenVerificationRequest request, string token, string apiVersion)
{
var verificationResult = _verifier.Verify(request, token);
return verificationResult.Match(
whenSuccessful: entitlement => CreateEntitlementApprovedResponse(apiVersion, entitlement),
whenSuccessful: tokenProperties => CreateApprovalSuccessResponse(apiVersion, tokenProperties),
whenFailure: errors => CreateEntitlementDeniedResponse(request.ApplicationId, errors));
}
/// <summary>
/// Attempts to extracts all the parameters required for validating an entitlement request.
/// Attempts to extracts all the parameters required for validating an entitlement approval request.
/// Any error here reflects a badly formed request.
/// </summary>
/// <param name="apiVersion">The API version from the query string</param>
/// <param name="httpContext">The HTTP context of the request</param>
/// <param name="requestBody">The information in the request body</param>
/// <returns>
/// A tuple in which either the <see cref="EntitlementVerificationRequest"/> and token values
/// A tuple in which either the <see cref="TokenVerificationRequest"/> and token values
/// are present if the request was well formed, or an informative error otherwise.
/// </returns>
private Errorable<(EntitlementVerificationRequest Request, string Token)> ExtractParameters(
string apiVersion,
private Errorable<(TokenVerificationRequest Request, string Token)> ExtractApprovalRequestParameters(
HttpContext httpContext,
SoftwareEntitlementRequestBody requestBody)
{
if (requestBody == null)
{
return Errorable.Failure<(EntitlementVerificationRequest, string)>(
return Errorable.Failure<(TokenVerificationRequest, string)>(
"Missing request body from software entitlement request.");
}
if (string.IsNullOrEmpty(requestBody.Token))
{
return Errorable.Failure<(EntitlementVerificationRequest, string)>(
return Errorable.Failure<(TokenVerificationRequest, string)>(
"Missing token from software entitlement request.");
}
if (string.IsNullOrEmpty(requestBody.ApplicationId))
{
return Errorable.Failure<(EntitlementVerificationRequest, string)>(
return Errorable.Failure<(TokenVerificationRequest, string)>(
"Missing applicationId value from software entitlement request.");
}
var remoteAddress = httpContext.Connection.RemoteIpAddress;
_logger.LogDebug("Remote Address: {Address}", remoteAddress);
var request = new EntitlementVerificationRequest(requestBody.ApplicationId, remoteAddress);
var request = new TokenVerificationRequest(requestBody.ApplicationId, remoteAddress);
return Errorable.Success((Request: request, Token: requestBody.Token));
}
private ObjectResult CreateEntitlementApprovedResponse(string apiVersion, NodeEntitlements entitlement)
private ObjectResult CreateApprovalSuccessResponse(string apiVersion, EntitlementTokenProperties tokenProperties)
{
var response = new SoftwareEntitlementSuccessfulResponse
{
EntitlementId = entitlement.Identifier,
// Return a value unique to this entitlement request, not the token identifier
// (retaining the original format of having an 'entitlement-' prefix).
EntitlementId = $"entitlement-{Guid.NewGuid()}"
};
if (ApiSupportsVirtualMachineId(apiVersion))
{
response.VirtualMachineId = entitlement.VirtualMachineId;
response.VirtualMachineId = tokenProperties.VirtualMachineId;
}
if (ApiSupportsExpiryTimestamp(apiVersion))
{
response.Expiry = entitlement.NotAfter;
response.Expiry = tokenProperties.NotAfter;
}
return Ok(response);

Просмотреть файл

@ -36,16 +36,16 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Server
{
services.AddMvc();
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.TryAddSingleton<IEntitlementParser>(provider =>
services.TryAddSingleton<ITokenPropertyParser>(provider =>
{
var serverOptions = provider.GetService<SoftwareEntitlementsController.ServerOptions>();
return new JwtEntitlementParser(
return new JwtPropertyParser(
serverOptions.Audience,
serverOptions.Issuer,
serverOptions.SigningKey,
serverOptions.EncryptionKey);
});
services.TryAddSingleton<EntitlementVerifier>();
services.TryAddSingleton<TokenVerifier>();
}
[SuppressMessage(

Просмотреть файл

@ -1,4 +1,4 @@
namespace Microsoft.Azure.Batch.SoftwareEntitlement
namespace Microsoft.Azure.Batch.SoftwareEntitlement
{
/// <summary>
/// Values used to define the claims used in our software entitlement token
@ -6,7 +6,7 @@
public static class Claims
{
/// <summary>
/// The identifier to use for application entitlement claims
/// The identifier to use for allowed application claims
/// </summary>
public const string Application = "app";
@ -18,9 +18,9 @@
public const string DefaultAudience = "https://batch.azure.test/software-entitlement";
/// <summary>
/// The identifier to use for the actual entitlement id
/// The identifier to use for the token id
/// </summary>
public const string EntitlementId = "id";
public const string TokenId = "id";
/// <summary>
/// The identifier to use for the ip address of the entitled machine

Просмотреть файл

@ -8,9 +8,9 @@ using Microsoft.Azure.Batch.SoftwareEntitlement.Common;
namespace Microsoft.Azure.Batch.SoftwareEntitlement
{
/// <summary>
/// The software entitlements for a specific compute node
/// The properties encoded in a token for a specific compute node
/// </summary>
public class NodeEntitlements
public class EntitlementTokenProperties
{
/// <summary>
/// Gets the virtual machine identifier for the machine entitled to use the specified packages
@ -18,17 +18,17 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
public string VirtualMachineId { get; }
/// <summary>
/// The moment at which the entitlement is issued
/// The moment at which the token is issued
/// </summary>
public DateTimeOffset IssuedAt { get; }
/// <summary>
/// The earliest moment at which the entitlement is active
/// The earliest moment at which the token is active
/// </summary>
public DateTimeOffset NotBefore { get; }
/// <summary>
/// The latest moment at which the entitlement is active
/// The latest moment at which the token is active
/// </summary>
public DateTimeOffset NotAfter { get; }
@ -38,17 +38,17 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
public ImmutableHashSet<string> Applications { get; }
/// <summary>
/// The IP addresses of the machine authorized to use this entitlement
/// The IP addresses of the machine authorized to use this token
/// </summary>
public ImmutableHashSet<IPAddress> IpAddresses { get; }
/// <summary>
/// The unique identifier for this entitlement
/// The unique identifier for this token
/// </summary>
public string Identifier { get; }
/// <summary>
/// The audience for whom this entitlement is intended
/// The audience for whom this token is intended
/// </summary>
public string Audience { get; }
@ -58,17 +58,17 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
public string Issuer { get; }
/// <summary>
/// Initializes a new instance of the <see cref="NodeEntitlements"/> class
/// Initializes a new instance of the <see cref="EntitlementTokenProperties"/> class
/// </summary>
public NodeEntitlements()
public EntitlementTokenProperties()
{
Applications = ImmutableHashSet<string>.Empty;
IpAddresses = ImmutableHashSet<IPAddress>.Empty;
}
public static Errorable<NodeEntitlements> Build(IEntitlementPropertyProvider provider)
public static Errorable<EntitlementTokenProperties> Build(ITokenPropertyProvider provider)
{
return Errorable.Success(new NodeEntitlements())
return Errorable.Success(new EntitlementTokenProperties())
.With(provider.NotBefore()).Map((e, val) => e.FromInstant(val))
.With(provider.NotAfter()).Map((e, val) => e.UntilInstant(val))
.With(provider.IssuedAt()).Map((e, val) => e.WithIssuedAt(val))
@ -77,55 +77,55 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
.With(provider.ApplicationIds()).Map((e, vals) => e.WithApplications(vals))
.With(provider.IpAddresses()).Map((e, vals) => e.WithIpAddresses(vals))
.With(provider.VirtualMachineId()).Map((e, val) => e.WithVirtualMachineId(val))
.With(provider.EntitlementId()).Map((e, val) => e.WithIdentifier(val));
.With(provider.TokenId()).Map((e, val) => e.WithIdentifier(val));
}
/// <summary>
/// Specify the virtual machine Id of the machine
/// </summary>
/// <param name="virtualMachineId">Virtual machine ID to include in the entitlement.</param>
/// <returns>A new entitlement.</returns>
public NodeEntitlements WithVirtualMachineId(string virtualMachineId)
/// <param name="virtualMachineId">Virtual machine ID to include in the token.</param>
/// <returns>A new <see cref="EntitlementTokenProperties"/> instance.</returns>
public EntitlementTokenProperties WithVirtualMachineId(string virtualMachineId)
{
return new NodeEntitlements(this, virtualMachineId: Specify.As(virtualMachineId));
return new EntitlementTokenProperties(this, virtualMachineId: Specify.As(virtualMachineId));
}
/// <summary>
/// Specify the instant at which the token is issued
/// </summary>
/// <param name="issuedAt">Date the token is issued.</param>
/// <returns>A new entitlement.</returns>
public NodeEntitlements WithIssuedAt(DateTimeOffset issuedAt)
/// <returns>A new <see cref="EntitlementTokenProperties"/> instance.</returns>
public EntitlementTokenProperties WithIssuedAt(DateTimeOffset issuedAt)
{
return new NodeEntitlements(this, issuedAt: Specify.As(issuedAt));
return new EntitlementTokenProperties(this, issuedAt: Specify.As(issuedAt));
}
/// <summary>
/// Specify an instant before which the token will not be valid
/// </summary>
/// <param name="notBefore">Earliest instant of availability.</param>
/// <returns>A new entitlement.</returns>
public NodeEntitlements FromInstant(DateTimeOffset notBefore)
/// <returns>A new <see cref="EntitlementTokenProperties"/> instance.</returns>
public EntitlementTokenProperties FromInstant(DateTimeOffset notBefore)
{
return new NodeEntitlements(this, notBefore: Specify.As(notBefore));
return new EntitlementTokenProperties(this, notBefore: Specify.As(notBefore));
}
/// <summary>
/// Specify an instant before which the token will not be valid
/// </summary>
/// <param name="notAfter">Earliest instant of availability.</param>
/// <returns></returns>
public NodeEntitlements UntilInstant(DateTimeOffset notAfter)
/// <returns>A new <see cref="EntitlementTokenProperties"/> instance.</returns>
public EntitlementTokenProperties UntilInstant(DateTimeOffset notAfter)
{
return new NodeEntitlements(this, notAfter: Specify.As(notAfter));
return new EntitlementTokenProperties(this, notAfter: Specify.As(notAfter));
}
/// <summary>
/// Specify the entitled applications
/// </summary>
/// <param name="application">Identifiers of the applications.</param>
/// <returns>A new entitlement.</returns>
public NodeEntitlements WithApplications(params string[] applications)
/// <param name="applications">Identifiers of the applications.</param>
/// <returns>A new <see cref="EntitlementTokenProperties"/> instance.</returns>
public EntitlementTokenProperties WithApplications(params string[] applications)
{
if (applications == null)
{
@ -138,9 +138,9 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
/// <summary>
/// Specify the list of entitled applications
/// </summary>
/// <param name="application">Identifiers of the applications.</param>
/// <returns>A new entitlement.</returns>
public NodeEntitlements WithApplications(IEnumerable<string> applications)
/// <param name="applications">Identifiers of the applications.</param>
/// <returns>A new <see cref="EntitlementTokenProperties"/> instance.</returns>
public EntitlementTokenProperties WithApplications(IEnumerable<string> applications)
{
if (applications == null)
{
@ -148,15 +148,15 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
}
applications = applications.Select(appId => appId.Trim());
return new NodeEntitlements(this, applications: ImmutableHashSet.CreateRange(applications));
return new EntitlementTokenProperties(this, applications: ImmutableHashSet.CreateRange(applications));
}
/// <summary>
/// Specify the IPAddresses of the entitled machine
/// </summary>
/// <param name="address">IP Addresses of the machine to run the entitled application(s).</param>
/// <returns>A new entitlement</returns>
public NodeEntitlements WithIpAddresses(params IPAddress[] ipAddresses)
/// <param name="ipAddresses">IP Addresses of the machine to run the entitled application(s).</param>
/// <returns>A new <see cref="EntitlementTokenProperties"/> instance.</returns>
public EntitlementTokenProperties WithIpAddresses(params IPAddress[] ipAddresses)
{
if (ipAddresses == null)
{
@ -169,75 +169,75 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
/// <summary>
/// Specify the list of IPAddresses of the entitled machine
/// </summary>
/// <param name="address">IP Addresses of the machine to run the entitled application(s).</param>
/// <returns>A new entitlement</returns>
public NodeEntitlements WithIpAddresses(IEnumerable<IPAddress> ipAddresses)
/// <param name="ipAddresses">IP Addresses of the machine to run the entitled application(s).</param>
/// <returns>A new <see cref="EntitlementTokenProperties"/> instance.</returns>
public EntitlementTokenProperties WithIpAddresses(IEnumerable<IPAddress> ipAddresses)
{
if (ipAddresses == null)
{
throw new ArgumentNullException(nameof(ipAddresses));
}
return new NodeEntitlements(this, addresses: ImmutableHashSet.CreateRange(ipAddresses));
return new EntitlementTokenProperties(this, addresses: ImmutableHashSet.CreateRange(ipAddresses));
}
/// <summary>
/// Specify the entitlement Id to use
/// Specify the token Id to use
/// </summary>
/// <param name="identifier">The entitlement identifier to use for correlating activity.</param>
/// <returns>A new entitlement</returns>
public NodeEntitlements WithIdentifier(string identifier)
/// <param name="identifier">The token identifier to use for correlating activity.</param>
/// <returns>A new <see cref="EntitlementTokenProperties"/> instance.</returns>
public EntitlementTokenProperties WithIdentifier(string identifier)
{
return new NodeEntitlements(this, identifier: Specify.As(identifier));
return new EntitlementTokenProperties(this, identifier: Specify.As(identifier));
}
/// <summary>
/// Specify the audience to use in the token
/// </summary>
/// <param name="audience">The audience for the generated token.</param>
/// <returns>A new entitlement</returns>
public NodeEntitlements WithAudience(string audience)
/// <returns>A new <see cref="EntitlementTokenProperties"/> instance.</returns>
public EntitlementTokenProperties WithAudience(string audience)
{
if (string.IsNullOrEmpty(audience))
{
throw new ArgumentException("Expect to have an audience", nameof(audience));
}
return new NodeEntitlements(this, audience: Specify.As(audience));
return new EntitlementTokenProperties(this, audience: Specify.As(audience));
}
/// <summary>
/// Specify the issuer to use in the token
/// </summary>
/// <param name="issuer">The issuer for the generated token.</param>
/// <returns>A new entitlement</returns>
public NodeEntitlements WithIssuer(string issuer)
/// <returns>A new <see cref="EntitlementTokenProperties"/> instance.</returns>
public EntitlementTokenProperties WithIssuer(string issuer)
{
if (string.IsNullOrEmpty(issuer))
{
throw new ArgumentException("Expect to have an issuer", nameof(issuer));
}
return new NodeEntitlements(this, issuer: Specify.As(issuer));
return new EntitlementTokenProperties(this, issuer: Specify.As(issuer));
}
/// <summary>
/// Cloning constructor to initialize a new instance of the <see cref="NodeEntitlements"/>
/// Cloning constructor to initialize a new instance of the <see cref="EntitlementTokenProperties"/>
/// class as a (near) copy of an existing one.
/// </summary>
/// <remarks>Specify any of the optional parameters to modify the clone from the original.</remarks>
/// <param name="original">Original entitlement to clone.</param>
/// <param name="original">Original token properties to clone.</param>
/// <param name="issuedAt">Optionally specify a new value for <see cref="IssuedAt"/></param>
/// <param name="notBefore">Optionally specify a new value for <see cref="NotBefore"/>.</param>
/// <param name="notAfter">Optionally specify a new value for <see cref="NotAfter"/>.</param>
/// <param name="virtualMachineId">Optionally specify a new value for <see cref="VirtualMachineId"/>.</param>
/// <param name="applications">The set of applications entitled to run.</param>
/// <param name="identifier">Identifier to use for this entitlement.</param>
/// <param name="identifier">Identifier to use for this token.</param>
/// <param name="addresses">Addresses of the entitled machine.</param>
/// <param name="audience">Audience for whom the token is intended.</param>
/// <param name="issuer">Issuer identifier for the token.</param>
private NodeEntitlements(
NodeEntitlements original,
private EntitlementTokenProperties(
EntitlementTokenProperties original,
Specifiable<DateTimeOffset> issuedAt = default,
Specifiable<DateTimeOffset> notBefore = default,
Specifiable<DateTimeOffset> notAfter = default,

Просмотреть файл

@ -1,62 +0,0 @@
using System;
using System.Linq;
using Microsoft.Azure.Batch.SoftwareEntitlement.Common;
namespace Microsoft.Azure.Batch.SoftwareEntitlement
{
/// <summary>
/// Verifies whether a software entitlement request is valid or not
/// </summary>
public class EntitlementVerifier
{
private readonly IEntitlementParser _entitlementParser;
/// <summary>
/// Constructs a new <see cref="EntitlementVerifier"/>
/// </summary>
/// <param name="tokenParser">Extracts identity information from a string token</param>
public EntitlementVerifier(IEntitlementParser entitlementParser)
{
_entitlementParser = entitlementParser ?? throw new ArgumentNullException(nameof(entitlementParser));
}
/// <summary>
/// Verifies an entitlement request against the specified token.
/// </summary>
/// <param name="request">The entitlement request</param>
/// <param name="token">The token string containing the entitlements</param>
/// <returns>An <see cref="Errorable{NodeEntitlements}"/> containing the validated
/// <see cref="NodeEntitlements"/> if validation was successful, or one or more
/// validation errors otherwise.</returns>
public Errorable<NodeEntitlements> Verify(
EntitlementVerificationRequest request,
string token)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return _entitlementParser
.Parse(token)
.Bind(e => Verify(request, e));
}
private static Errorable<NodeEntitlements> Verify(
EntitlementVerificationRequest request,
NodeEntitlements entitlement)
{
if (!entitlement.Applications.Any(a => string.Equals(a, request.ApplicationId, StringComparison.OrdinalIgnoreCase)))
{
return Errorable.Failure<NodeEntitlements>($"Token does not grant entitlement for {request.ApplicationId}");
}
if (!entitlement.IpAddresses.Any(addr => addr.Equals(request.IpAddress)))
{
return Errorable.Failure<NodeEntitlements>($"Token does not grant entitlement for {request.IpAddress}");
}
return Errorable.Success(entitlement);
}
}
}

Просмотреть файл

@ -3,20 +3,20 @@ using Microsoft.Azure.Batch.SoftwareEntitlement.Common;
namespace Microsoft.Azure.Batch.SoftwareEntitlement
{
/// <summary>
/// Responsible for parsing a string token and extracting a <see cref="NodeEntitlements"/>
/// Responsible for parsing a string token and extracting a <see cref="EntitlementTokenProperties"/>
/// from it.
/// </summary>
public interface IEntitlementParser
public interface ITokenPropertyParser
{
/// <summary>
/// Parses a token and builds a <see cref="NodeEntitlements"/> object, or an <see cref="Errorable"/>
/// Parses a token and builds a <see cref="EntitlementTokenProperties"/> object, or an <see cref="Errorable"/>
/// if any parsing or validation error occurs.
/// </summary>
/// <param name="token">A string token</param>
/// <returns>
/// An <see cref="Errorable{NodeEntitlements}"/> containing the result, or an
/// <see cref="Errorable.Failure{NodeEntitlements}"/> if it failed to validate correctly.
/// An <see cref="Errorable{TokenProperties}"/> containing the result, or an
/// error if it failed to validate correctly.
/// </returns>
Errorable<NodeEntitlements> Parse(string token);
Errorable<EntitlementTokenProperties> Parse(string token);
}
}

Просмотреть файл

@ -6,29 +6,29 @@ using Microsoft.Azure.Batch.SoftwareEntitlement.Common;
namespace Microsoft.Azure.Batch.SoftwareEntitlement
{
/// <summary>
/// Supplies all the property values required to build a <see cref="NodeEntitlements"/> object.
/// Supplies all the property values required to build a <see cref="EntitlementTokenProperties"/> object.
/// Responsible for performing validation and returning error results for properties which cannot
/// be populated.
/// </summary>
public interface IEntitlementPropertyProvider
public interface ITokenPropertyProvider
{
/// <summary>
/// Gets the moment at which the entitlement is issued
/// Gets the moment at which the token is issued
/// </summary>
Errorable<DateTimeOffset> IssuedAt();
/// <summary>
/// Gets the earliest moment at which the entitlement is active
/// Gets the earliest moment at which the token is active
/// </summary>
Errorable<DateTimeOffset> NotBefore();
/// <summary>
/// Gets the latest moment at which the entitlement is active
/// Gets the latest moment at which the token is active
/// </summary>
Errorable<DateTimeOffset> NotAfter();
/// <summary>
/// Gets the audience for whom the entitlement is intended
/// Gets the audience for whom the token is intended
/// </summary>
Errorable<string> Audience();
@ -43,7 +43,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
Errorable<IEnumerable<string>> ApplicationIds();
/// <summary>
/// Gets the IP addresses of the machine authorized to use this entitlement
/// Gets the IP addresses of the machine authorized to use this token
/// </summary>
Errorable<IEnumerable<IPAddress>> IpAddresses();
@ -53,8 +53,8 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
Errorable<string> VirtualMachineId();
/// <summary>
/// Gets the unique identifier for the entitlement
/// Gets the unique identifier for the token
/// </summary>
Errorable<string> EntitlementId();
Errorable<string> TokenId();
}
}

Просмотреть файл

@ -8,10 +8,10 @@ using Microsoft.IdentityModel.Tokens;
namespace Microsoft.Azure.Batch.SoftwareEntitlement
{
/// <summary>
/// An <see cref="IEntitlementParser"/> implementation for extracting <see cref="NodeEntitlements"/>
/// An <see cref="ITokenPropertyParser"/> implementation for extracting <see cref="EntitlementTokenProperties"/>
/// objects from JWT tokens.
/// </summary>
public class JwtEntitlementParser : IEntitlementParser
public class JwtPropertyParser : ITokenPropertyParser
{
private readonly string _expectedAudience;
private readonly string _expectedIssuer;
@ -19,13 +19,13 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
private readonly SecurityKey _encryptionKey;
/// <summary>
/// Creates a <see cref="JwtEntitlementParser"/> instance.
/// Creates a <see cref="JwtPropertyParser"/> instance.
/// </summary>
/// <param name="expectedAudience">The audience value expected to be found in the tokens to be parsed.</param>
/// <param name="expectedIssuer">The issuer value expected to be found in the tokens to be parsed.</param>
/// <param name="signingKey">The key that the tokens are expected to be signed with, or null if not signed.</param>
/// <param name="encryptingKey">The key that the tokens are expected to be encrypted with, or null if not encrypted.</param>
public JwtEntitlementParser(
public JwtPropertyParser(
string expectedAudience,
string expectedIssuer,
SecurityKey signingKey = null,
@ -38,21 +38,21 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
}
/// <summary>
/// Builds a <see cref="NodeEntitlements"/> from a JWT token string.
/// Builds a <see cref="EntitlementTokenProperties"/> from a JWT token string.
/// </summary>
/// <param name="token">The JWT token string</param>
/// <returns>
/// An <see cref="Errorable{NodeEntitlements}"/> containing the result, or an
/// <see cref="Errorable.Failure{NodeEntitlements}"/> if it failed to validate correctly.
/// error if it failed to validate correctly.
/// </returns>
public Errorable<NodeEntitlements> Parse(string token)
public Errorable<EntitlementTokenProperties> Parse(string token)
{
return ExtractJwt(token).Map(CreateEntitlementPropertyProvider).Bind(NodeEntitlements.Build);
return ExtractJwt(token).Map(CreateEntitlementPropertyProvider).Bind(EntitlementTokenProperties.Build);
}
private static IEntitlementPropertyProvider CreateEntitlementPropertyProvider(ClaimsPrincipal principal, JwtSecurityToken jwt)
private static ITokenPropertyProvider CreateEntitlementPropertyProvider(ClaimsPrincipal principal, JwtSecurityToken jwt)
{
return new JwtEntitlementPropertyProvider(principal, jwt);
return new JwtPropertyProvider(principal, jwt);
}
private Errorable<(ClaimsPrincipal Principal, JwtSecurityToken Token)> ExtractJwt(string tokenString)

Просмотреть файл

@ -10,27 +10,27 @@ using Microsoft.IdentityModel.Tokens;
namespace Microsoft.Azure.Batch.SoftwareEntitlement
{
/// <summary>
/// An <see cref="IEntitlementPropertyProvider"/> implementation for extracting <see cref="NodeEntitlements"/>
/// An <see cref="ITokenPropertyProvider"/> implementation for extracting <see cref="EntitlementTokenProperties"/>
/// information from a <see cref="JwtSecurityToken"/> and its corresponding <see cref="ClaimsPrincipal"/>.
/// </summary>
public class JwtEntitlementPropertyProvider : IEntitlementPropertyProvider
public class JwtPropertyProvider : ITokenPropertyProvider
{
private readonly ClaimsPrincipal _principal;
private readonly JwtSecurityToken _jwt;
/// <summary>
/// Creates a <see cref="JwtEntitlementPropertyProvider"/> instance from a JWT object and claims principal.
/// Creates a <see cref="JwtPropertyProvider"/> instance from a JWT object and claims principal.
/// </summary>
/// <param name="principal">A <see cref="ClaimsPrincipal"/> extracted from a JWT token.</param>
/// <param name="jwt">A <see cref="JwtSecurityToken"/> object.</param>
public JwtEntitlementPropertyProvider(ClaimsPrincipal principal, JwtSecurityToken jwt)
public JwtPropertyProvider(ClaimsPrincipal principal, JwtSecurityToken jwt)
{
_principal = principal ?? throw new ArgumentNullException(nameof(principal));
_jwt = jwt ?? throw new ArgumentNullException(nameof(jwt));
}
/// <summary>
/// Gets the moment at which the entitlement is issued from the 'iat' claim on the JWT.
/// Gets the moment at which the token is issued from the 'iat' claim on the JWT.
/// </summary>
public Errorable<DateTimeOffset> IssuedAt()
{
@ -44,25 +44,25 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
}
/// <summary>
/// Gets the earliest moment at which the entitlement is active from the 'nbf' claim on the JWT.
/// Gets the earliest moment at which the token is active from the 'nbf' claim on the JWT.
/// </summary>
public Errorable<DateTimeOffset> NotBefore()
=> Errorable.Success(new DateTimeOffset(_jwt.ValidFrom));
/// <summary>
/// Gets the latest moment at which the entitlement is active from the 'exp' claim on the JWT.
/// Gets the latest moment at which the token is active from the 'exp' claim on the JWT.
/// </summary>
public Errorable<DateTimeOffset> NotAfter()
=> Errorable.Success(new DateTimeOffset(_jwt.ValidTo));
/// <summary>
/// Gets the audience for whom the entitlement is intended from the 'aud' claim on the JWT, or
/// Gets the audience for whom the token is intended from the 'aud' claim on the JWT, or
/// an error if there are zero or many such claims.
/// </summary>
public Errorable<string> Audience()
{
// We don't expect multiple audiences to appear in the token
var audiences = _jwt.Audiences.ToList();
var audiences = _jwt.Audiences?.ToList();
if (audiences == null || !audiences.Any())
{
return Errorable.Failure<string>("No audience claim found in token.");
@ -77,7 +77,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
}
/// <summary>
/// Gets the issuer who hands out entitlement tokens from the 'iss' claim on the JWT.
/// Gets the issuer who hands out token tokens from the 'iss' claim on the JWT.
/// </summary>
public Errorable<string> Issuer()
=> Errorable.Success(_jwt.Issuer);
@ -97,7 +97,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
}
/// <summary>
/// Gets the IP addresses of the machine authorized to use this entitlement from the claims in the principal.
/// Gets the IP addresses of the machine authorized to use this token from the claims in the principal.
/// </summary>
public Errorable<IEnumerable<IPAddress>> IpAddresses()
=> ReadAll(Claims.IpAddress).Select(ParseIpAddress).Reduce();
@ -110,14 +110,14 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
=> Errorable.Success(Read(Claims.VirtualMachineId));
/// <summary>
/// Gets the unique identifier for the entitlement from a claim in the principal.
/// Gets the unique identifier for the token from a claim in the principal.
/// </summary>
public Errorable<string> EntitlementId()
public Errorable<string> TokenId()
{
var entitlementId = Read(Claims.EntitlementId);
var entitlementId = Read(Claims.TokenId);
if (string.IsNullOrEmpty(entitlementId))
{
return Errorable.Failure<string>("Missing entitlement identifier in token.");
return Errorable.Failure<string>("Missing token identifier in token.");
}
return Errorable.Success(entitlementId);

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>

Просмотреть файл

@ -10,7 +10,7 @@ using Microsoft.IdentityModel.Tokens;
namespace Microsoft.Azure.Batch.SoftwareEntitlement
{
/// <summary>
/// Generator to create a token given a fully configured software entitlement
/// Generator to create a token given a fully configured <see cref="EntitlementTokenProperties"/>
/// </summary>
public class TokenGenerator
{
@ -44,23 +44,23 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
}
/// <summary>
/// Generate a token from a software entitlement
/// Generate a token from a <see cref="EntitlementTokenProperties"/>
/// </summary>
/// <param name="entitlements">Software entitlements to use when populating the token.</param>
/// <param name="tokenProperties">Software entitlements to use when populating the token.</param>
/// <returns>The generated token.</returns>
public string Generate(NodeEntitlements entitlements)
public string Generate(EntitlementTokenProperties tokenProperties)
{
if (entitlements == null)
if (tokenProperties == null)
{
throw new ArgumentNullException(nameof(entitlements));
throw new ArgumentNullException(nameof(tokenProperties));
}
_logger.LogDebug(
"Not Before: {NotBefore}",
entitlements.NotBefore.ToString(TimestampParser.ExpectedFormat, CultureInfo.InvariantCulture));
tokenProperties.NotBefore.ToString(TimestampParser.ExpectedFormat, CultureInfo.InvariantCulture));
_logger.LogDebug(
"Not After: {NotAfter}",
entitlements.NotAfter.ToString(TimestampParser.ExpectedFormat, CultureInfo.InvariantCulture));
tokenProperties.NotAfter.ToString(TimestampParser.ExpectedFormat, CultureInfo.InvariantCulture));
if (SigningCredentials != null)
{
@ -77,19 +77,19 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
EncryptingCredentials.Key.KeyId);
}
_logger.LogDebug("Issued by {Issuer}", entitlements.Issuer);
_logger.LogDebug("Audience is {Audience}", entitlements.Audience);
_logger.LogDebug("Issued by {Issuer}", tokenProperties.Issuer);
_logger.LogDebug("Audience is {Audience}", tokenProperties.Audience);
var claims = CreateClaims(entitlements);
var claims = CreateClaims(tokenProperties);
var claimsIdentity = new ClaimsIdentity(claims);
var securityTokenDescriptor = new SecurityTokenDescriptor
{
Subject = claimsIdentity,
NotBefore = entitlements.NotBefore.UtcDateTime,
Expires = entitlements.NotAfter.UtcDateTime,
IssuedAt = entitlements.IssuedAt.UtcDateTime,
Issuer = entitlements.Issuer,
Audience = entitlements.Audience,
NotBefore = tokenProperties.NotBefore.UtcDateTime,
Expires = tokenProperties.NotAfter.UtcDateTime,
IssuedAt = tokenProperties.IssuedAt.UtcDateTime,
Issuer = tokenProperties.Issuer,
Audience = tokenProperties.Audience,
SigningCredentials = SigningCredentials,
EncryptingCredentials = EncryptingCredentials
};
@ -102,29 +102,29 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
return handler.WriteToken(token);
}
private List<Claim> CreateClaims(NodeEntitlements entitlements)
private List<Claim> CreateClaims(EntitlementTokenProperties tokenProperties)
{
var claims = new List<Claim>();
if (!string.IsNullOrEmpty(entitlements.VirtualMachineId))
if (!string.IsNullOrEmpty(tokenProperties.VirtualMachineId))
{
_logger.LogDebug("Virtual machine Id: {VirtualMachineId}", entitlements.VirtualMachineId);
claims.Add(new Claim(Claims.VirtualMachineId, entitlements.VirtualMachineId));
_logger.LogDebug("Virtual machine Id: {VirtualMachineId}", tokenProperties.VirtualMachineId);
claims.Add(new Claim(Claims.VirtualMachineId, tokenProperties.VirtualMachineId));
}
if (!string.IsNullOrEmpty(entitlements.Identifier))
if (!string.IsNullOrEmpty(tokenProperties.Identifier))
{
_logger.LogDebug("Entitlement Id: {EntitlementId}", entitlements.Identifier);
claims.Add(new Claim(Claims.EntitlementId, entitlements.Identifier));
_logger.LogDebug("Token Id: {TokenId}", tokenProperties.Identifier);
claims.Add(new Claim(Claims.TokenId, tokenProperties.Identifier));
}
foreach (var ip in entitlements.IpAddresses)
foreach (var ip in tokenProperties.IpAddresses)
{
_logger.LogDebug("IP Address: {IP}", ip);
claims.Add(new Claim(Claims.IpAddress, ip.ToString()));
}
foreach (var app in entitlements.Applications)
foreach (var app in tokenProperties.Applications)
{
_logger.LogDebug("Application Id: {ApplicationId}", app);
var claim = new Claim(Claims.Application, app);

Просмотреть файл

@ -10,14 +10,14 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
/// provided by Batch and passed on untouched by the application. This is the data that is compared
/// against the token's claims to determine whether the request is allowed.
/// </remarks>
public class EntitlementVerificationRequest
public class TokenVerificationRequest
{
/// <summary>
/// Initializes a new instance of an entitlement verification request
/// Initializes a new instance of an token verification request
/// </summary>
/// <param name="applicationId">The identifier for the application the entitlement is being requested for</param>
/// <param name="ipAddress">The observed IP address of the machine requesting the entitlement</param>
public EntitlementVerificationRequest(string applicationId, IPAddress ipAddress)
public TokenVerificationRequest(string applicationId, IPAddress ipAddress)
{
ApplicationId = applicationId;
IpAddress = ipAddress;

Просмотреть файл

@ -0,0 +1,62 @@
using System;
using System.Linq;
using Microsoft.Azure.Batch.SoftwareEntitlement.Common;
namespace Microsoft.Azure.Batch.SoftwareEntitlement
{
/// <summary>
/// Verifies whether a software entitlement request is valid or not
/// </summary>
public class TokenVerifier
{
private readonly ITokenPropertyParser _tokenPropertyParser;
/// <summary>
/// Constructs a new <see cref="TokenVerifier"/>
/// </summary>
/// <param name="tokenPropertyParser">Extracts identity information from a string token</param>
public TokenVerifier(ITokenPropertyParser tokenPropertyParser)
{
_tokenPropertyParser = tokenPropertyParser ?? throw new ArgumentNullException(nameof(tokenPropertyParser));
}
/// <summary>
/// Verifies an entitlement request against the specified token.
/// </summary>
/// <param name="request">The entitlement request</param>
/// <param name="token">The token string containing the entitlements</param>
/// <returns>An <see cref="Errorable{NodeEntitlements}"/> containing the validated
/// <see cref="EntitlementTokenProperties"/> if validation was successful, or one or more
/// validation errors otherwise.</returns>
public Errorable<EntitlementTokenProperties> Verify(
TokenVerificationRequest request,
string token)
{
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
return _tokenPropertyParser
.Parse(token)
.Bind(e => Verify(request, e));
}
private static Errorable<EntitlementTokenProperties> Verify(
TokenVerificationRequest request,
EntitlementTokenProperties tokenProperties)
{
if (!tokenProperties.Applications.Any(a => string.Equals(a, request.ApplicationId, StringComparison.OrdinalIgnoreCase)))
{
return Errorable.Failure<EntitlementTokenProperties>($"Token does not grant entitlement for {request.ApplicationId}");
}
if (!tokenProperties.IpAddresses.Any(addr => addr.Equals(request.IpAddress)))
{
return Errorable.Failure<EntitlementTokenProperties>($"Token does not grant entitlement for {request.IpAddress}");
}
return Errorable.Success(tokenProperties);
}
}
}

Просмотреть файл

@ -8,10 +8,10 @@ using System.Net.NetworkInformation;
namespace Microsoft.Azure.Batch.SoftwareEntitlement
{
/// <summary>
/// A factory object that tries to create a <see cref="NodeEntitlements"/> instance when given
/// A factory object that tries to create a <see cref="EntitlementTokenProperties"/> instance when given
/// the <see cref="GenerateCommandLine"/> specified by the user.
/// </summary>
public class CommandLineEntitlementPropertyProvider : IEntitlementPropertyProvider
public class CommandLineEntitlementPropertyProvider : ITokenPropertyProvider
{
// Reference to the generate command line we wrap
private readonly GenerateCommandLine _commandLine;
@ -22,7 +22,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
// A steady reference for "now"
private readonly DateTimeOffset _now = DateTimeOffset.Now;
private readonly string _entitlementId = $"entitlement-{Guid.NewGuid():D}";
private readonly string _tokenId = $"token-{Guid.NewGuid():D}";
/// <summary>
/// Initializes a new instance of the <see cref="GenerateCommandLine"/> class
@ -145,7 +145,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
public Errorable<string> VirtualMachineId()
=> Errorable.Success(_commandLine.VirtualMachineId);
public Errorable<string> EntitlementId()
=> Errorable.Success(_entitlementId);
public Errorable<string> TokenId()
=> Errorable.Success(_tokenId);
}
}

Просмотреть файл

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Azure.Batch.SoftwareEntitlement.Common;
@ -32,11 +31,11 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
public int Execute(GenerateCommandLine commandLine)
{
var provider = new CommandLineEntitlementPropertyProvider(commandLine);
Errorable<NodeEntitlements> entitlement = NodeEntitlements.Build(provider);
Errorable<EntitlementTokenProperties> tokenProperties = EntitlementTokenProperties.Build(provider);
Errorable<X509Certificate2> signingCert = FindCertificate("signing", commandLine.SignatureThumbprint);
Errorable<X509Certificate2> encryptionCert = FindCertificate("encryption", commandLine.EncryptionThumbprint);
Errorable<string> result = entitlement.With(signingCert).With(encryptionCert)
Errorable<string> result = tokenProperties.With(signingCert).With(encryptionCert)
.Map(GenerateToken);
if (!result.HasValue)
@ -69,12 +68,12 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
/// <summary>
/// Generate a token
/// </summary>
/// <param name="entitlements">Details of the entitlements to encode into the token.</param>
/// <param name="tokenProperties">The properties to encode into the token.</param>
/// <param name="signingCert">Certificate to use when signing the token (optional).</param>
/// <param name="encryptionCert">Certificate to use when encrypting the token (optional).</param>
/// <returns>Generated token, if any; otherwise all related errors.</returns>
private string GenerateToken(
NodeEntitlements entitlements,
EntitlementTokenProperties tokenProperties,
X509Certificate2 signingCert = null,
X509Certificate2 encryptionCert = null)
{
@ -94,7 +93,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
}
var generator = new TokenGenerator(Logger, signingCredentials, encryptingCredentials);
return generator.Generate(entitlements);
return generator.Generate(tokenProperties);
}
private static Errorable<X509Certificate2> FindCertificate(string purpose, string thumbprint)

Просмотреть файл

@ -6,7 +6,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement
[Verb("generate", HelpText = "Generate a token with specified parameters")]
public sealed class GenerateCommandLine : CommandLineBase
{
[Option("application-id", HelpText = "Unique identifier(s) for the applications(s) to include in the entitlement (comma separated).", Separator = ',')]
[Option("application-id", HelpText = "Unique identifier(s) for the applications(s) to include in the token (comma separated).", Separator = ',')]
public IList<string> ApplicationIds { get; set; } = new List<string>();
[Option("vmid", HelpText = "[Deprecated] Unique identifier for the Azure virtual machine.")]

Просмотреть файл

@ -5,10 +5,10 @@ using Xunit;
namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
{
public class NodeEntitlementsTests
public class EntitlementTokenPropertiesTests
{
// An empty software entitlement to use for testing
private readonly NodeEntitlements _emptyEntitlement = new NodeEntitlements();
private readonly EntitlementTokenProperties _emptyTokenProperties = new EntitlementTokenProperties();
// A Times span representing NZDT
private readonly TimeSpan _nzdt = new TimeSpan(+13, 0, 0);
@ -19,18 +19,18 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
// An instant to use as the finish for testing
private readonly DateTimeOffset _finish;
public NodeEntitlementsTests()
public EntitlementTokenPropertiesTests()
{
_start = new DateTimeOffset(2016, 2, 29, 16, 14, 12, _nzdt);
_finish = new DateTimeOffset(2016, 3, 31, 16, 14, 12, _nzdt);
}
public class WithVirtualMachineIdMethod : NodeEntitlementsTests
public class WithVirtualMachineIdMethod : EntitlementTokenPropertiesTests
{
[Fact]
public void GivenNull_SetsIdToNull()
{
_emptyEntitlement.WithVirtualMachineId(null)
_emptyTokenProperties.WithVirtualMachineId(null)
.VirtualMachineId.Should().Be(null);
}
@ -38,32 +38,32 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
public void GivenVirtualMachineId_ConfiguresProperty()
{
const string vmid = "Sample";
_emptyEntitlement.WithVirtualMachineId(vmid)
_emptyTokenProperties.WithVirtualMachineId(vmid)
.VirtualMachineId.Should().Be(vmid);
}
}
public class FromInstantMethod : NodeEntitlementsTests
public class FromInstantMethod : EntitlementTokenPropertiesTests
{
[Fact]
public void GivenStart_ConfiguresProperty()
{
_emptyEntitlement.FromInstant(_start)
_emptyTokenProperties.FromInstant(_start)
.NotBefore.Should().Be(_start);
}
}
public class UntilInstantMethod : NodeEntitlementsTests
public class UntilInstantMethod : EntitlementTokenPropertiesTests
{
[Fact]
public void GivenFinish_ConfiguresProperty()
{
_emptyEntitlement.UntilInstant(_finish)
_emptyTokenProperties.UntilInstant(_finish)
.NotAfter.Should().Be(_finish);
}
}
public class WithApplicationsMethod : NodeEntitlementsTests
public class WithApplicationsMethod : EntitlementTokenPropertiesTests
{
private const string Application = "contosoapp";
@ -72,37 +72,37 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
{
var exception =
Assert.Throws<ArgumentNullException>(
() => _emptyEntitlement.WithApplications(null));
() => _emptyTokenProperties.WithApplications(null));
exception.ParamName.Should().Be("applications");
}
[Fact]
public void GivenApplicationId_AddsToConfiguration()
{
var entitlement = _emptyEntitlement.WithApplications(Application);
entitlement.Applications.Should().HaveCount(1);
entitlement.Applications.Should().Contain(Application);
var tokenProperties = _emptyTokenProperties.WithApplications(Application);
tokenProperties.Applications.Should().HaveCount(1);
tokenProperties.Applications.Should().Contain(Application);
}
[Fact]
public void GivenDuplicateApplicationId_DoesNotAddToConfiguration()
{
var entitlement = _emptyEntitlement
var tokenProperties = _emptyTokenProperties
.WithApplications(Application, Application);
entitlement.Applications.Should().HaveCount(1);
entitlement.Applications.Should().Contain(Application);
tokenProperties.Applications.Should().HaveCount(1);
tokenProperties.Applications.Should().Contain(Application);
}
[Fact]
public void GivenApplicationIdWithWhitespace_RemovesWhitespace()
{
var entitlement = _emptyEntitlement.WithApplications(" " + Application + " ");
entitlement.Applications.Should().HaveCount(1);
entitlement.Applications.Should().Contain(Application.Trim());
var tokenProperties = _emptyTokenProperties.WithApplications(" " + Application + " ");
tokenProperties.Applications.Should().HaveCount(1);
tokenProperties.Applications.Should().Contain(Application.Trim());
}
}
public class AddIpAddressMethod : NodeEntitlementsTests
public class AddIpAddressMethod : EntitlementTokenPropertiesTests
{
// sample IPAddresses to use for testing (sample addresses as per RFC5735)
private readonly IPAddress _addressA = IPAddress.Parse("203.0.113.42");
@ -113,61 +113,61 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
{
var exception =
Assert.Throws<ArgumentNullException>(
() => _emptyEntitlement.WithIpAddresses(null));
() => _emptyTokenProperties.WithIpAddresses(null));
exception.ParamName.Should().Be("ipAddresses");
}
[Fact]
public void GivenIpAddress_ModifiesConfiguration()
{
var entitlement = _emptyEntitlement.WithIpAddresses(_addressA);
entitlement.IpAddresses.Should().Contain(_addressA);
var tokenProperties = _emptyTokenProperties.WithIpAddresses(_addressA);
tokenProperties.IpAddresses.Should().Contain(_addressA);
}
[Fact]
public void GivenSecondIpAddress_ModifiesConfiguration()
{
var entitlement = _emptyEntitlement.WithIpAddresses(_addressB);
entitlement.IpAddresses.Should().Contain(_addressB);
var tokenProperties = _emptyTokenProperties.WithIpAddresses(_addressB);
tokenProperties.IpAddresses.Should().Contain(_addressB);
}
[Fact]
public void GivenSecondIpAddress_RetainsFirst()
{
var entitlement = _emptyEntitlement
var tokenProperties = _emptyTokenProperties
.WithIpAddresses(_addressA, _addressB);
entitlement.IpAddresses.Should().Contain(_addressA);
tokenProperties.IpAddresses.Should().Contain(_addressA);
}
}
public class WithIdentifierMethod : NodeEntitlementsTests
public class WithIdentifierMethod : EntitlementTokenPropertiesTests
{
// An identifier to use
private readonly string _identifier = "an-identifier-for-an-entitlement";
private readonly string _identifier = "an-identifier-for-a-token";
[Fact]
public void GivenNull_SetsIdentifierToNull()
{
var entitlement = _emptyEntitlement.WithIdentifier(null);
entitlement.Identifier.Should().BeNull();
var tokenProperties = _emptyTokenProperties.WithIdentifier(null);
tokenProperties.Identifier.Should().BeNull();
}
[Fact]
public void GivenBlank_SetsIdentifierToEmpty()
{
var entitlement = _emptyEntitlement.WithIdentifier(string.Empty);
entitlement.Identifier.Should().BeEmpty();
var tokenProperties = _emptyTokenProperties.WithIdentifier(string.Empty);
tokenProperties.Identifier.Should().BeEmpty();
}
[Fact]
public void GivenIpAddress_ModifiesConfiguration()
{
var entitlement = _emptyEntitlement.WithIdentifier(_identifier);
entitlement.Identifier.Should().Be(_identifier);
var tokenProperties = _emptyTokenProperties.WithIdentifier(_identifier);
tokenProperties.Identifier.Should().Be(_identifier);
}
}
public class WithAudienceMethod : NodeEntitlementsTests
public class WithAudienceMethod : EntitlementTokenPropertiesTests
{
// An audience to use
private readonly string _audience = "http://batch.test.example.com/account";
@ -177,7 +177,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
{
var exception =
Assert.Throws<ArgumentException>(
() => _emptyEntitlement.WithAudience(null));
() => _emptyTokenProperties.WithAudience(null));
exception.ParamName.Should().Be("audience");
}
@ -186,21 +186,21 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
{
var exception =
Assert.Throws<ArgumentException>(
() => _emptyEntitlement.WithAudience(string.Empty));
() => _emptyTokenProperties.WithAudience(string.Empty));
exception.ParamName.Should().Be("audience");
}
[Fact]
public void GivenAudience_ModifiesConfiguration()
{
var entitlement = _emptyEntitlement.WithAudience(_audience);
entitlement.Audience.Should().Be(_audience);
var tokenProperties = _emptyTokenProperties.WithAudience(_audience);
tokenProperties.Audience.Should().Be(_audience);
}
}
public class Create : NodeEntitlementsTests
public class Create : EntitlementTokenPropertiesTests
{
private readonly FakeEntitlementPropertyProvider _validProvider = FakeEntitlementPropertyProvider.CreateValid();
private readonly FakeTokenPropertyProvider _validProvider = FakeTokenPropertyProvider.CreateValid();
[Fact]
public void GivenValidReader_ReturnsNoErrors()
@ -208,72 +208,72 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
// If this test fails, verify that the command line specified by _commandLine
// (above) correctly specifies a valid token; If this constraint is violated, most
// all of the tests later in this file might fail with spurious errors.
var entitlement = NodeEntitlements.Build(_validProvider);
entitlement.Errors.Should()
var tokenProperties = EntitlementTokenProperties.Build(_validProvider);
tokenProperties.Errors.Should()
.BeEmpty(because: $"the command line represented by {nameof(_validProvider)} should result in a valid token");
}
[Fact]
public void GivenValidReader_ApplicationIdsAreSet()
{
var entitlement = NodeEntitlements.Build(_validProvider);
entitlement.Value.Applications.Should().BeEquivalentTo(_validProvider.ApplicationIds.Value);
var tokenProperties = EntitlementTokenProperties.Build(_validProvider);
tokenProperties.Value.Applications.Should().BeEquivalentTo(_validProvider.ApplicationIds.Value);
}
[Fact]
public void GivenValidReader_AudienceIsSet()
{
var entitlement = NodeEntitlements.Build(_validProvider);
entitlement.Value.Audience.Should().Be(_validProvider.Audience.Value);
var tokenProperties = EntitlementTokenProperties.Build(_validProvider);
tokenProperties.Value.Audience.Should().Be(_validProvider.Audience.Value);
}
[Fact]
public void GivenValidReader_IdentifierIsSet()
{
var entitlement = NodeEntitlements.Build(_validProvider);
entitlement.Value.Identifier.Should().Be(_validProvider.EntitlementId.Value);
var tokenProperties = EntitlementTokenProperties.Build(_validProvider);
tokenProperties.Value.Identifier.Should().Be(_validProvider.TokenId.Value);
}
[Fact]
public void GivenValidReader_IpAddressesAreSet()
{
var entitlement = NodeEntitlements.Build(_validProvider);
entitlement.Value.IpAddresses.Should().BeEquivalentTo(_validProvider.IpAddresses.Value);
var tokenProperties = EntitlementTokenProperties.Build(_validProvider);
tokenProperties.Value.IpAddresses.Should().BeEquivalentTo(_validProvider.IpAddresses.Value);
}
[Fact]
public void GivenValidReader_IssuedAtIsSet()
{
var entitlement = NodeEntitlements.Build(_validProvider);
entitlement.Value.IssuedAt.Should().Be(_validProvider.IssuedAt.Value);
var tokenProperties = EntitlementTokenProperties.Build(_validProvider);
tokenProperties.Value.IssuedAt.Should().Be(_validProvider.IssuedAt.Value);
}
[Fact]
public void GivenValidReader_IssuerIsSet()
{
var entitlement = NodeEntitlements.Build(_validProvider);
entitlement.Value.Issuer.Should().Be(_validProvider.Issuer.Value);
var tokenProperties = EntitlementTokenProperties.Build(_validProvider);
tokenProperties.Value.Issuer.Should().Be(_validProvider.Issuer.Value);
}
[Fact]
public void GivenValidReader_NotAfterIsSet()
{
var entitlement = NodeEntitlements.Build(_validProvider);
entitlement.Value.NotAfter.Should().Be(_validProvider.NotAfter.Value);
var tokenProperties = EntitlementTokenProperties.Build(_validProvider);
tokenProperties.Value.NotAfter.Should().Be(_validProvider.NotAfter.Value);
}
[Fact]
public void GivenValidReader_NotBeforeIsSet()
{
var entitlement = NodeEntitlements.Build(_validProvider);
entitlement.Value.NotBefore.Should().Be(_validProvider.NotBefore.Value);
var tokenProperties = EntitlementTokenProperties.Build(_validProvider);
tokenProperties.Value.NotBefore.Should().Be(_validProvider.NotBefore.Value);
}
[Fact]
public void GivenValidReader_VirtualMachineIdIsSet()
{
var entitlement = NodeEntitlements.Build(_validProvider);
entitlement.Value.VirtualMachineId.Should().Be(_validProvider.VirtualMachineId.Value);
var tokenProperties = EntitlementTokenProperties.Build(_validProvider);
tokenProperties.Value.VirtualMachineId.Should().Be(_validProvider.VirtualMachineId.Value);
}
}
}

Просмотреть файл

@ -5,20 +5,20 @@ using Microsoft.Azure.Batch.SoftwareEntitlement.Common;
namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
{
public class FakeEntitlementParser : IEntitlementParser
public class FakeTokenPropertyParser : ITokenPropertyParser
{
private readonly Dictionary<string, Errorable<NodeEntitlements>> _outputLookup;
private readonly Dictionary<string, Errorable<EntitlementTokenProperties>> _outputLookup;
public FakeEntitlementParser(string token, NodeEntitlements result) : this((token, Errorable.Success(result)))
public FakeTokenPropertyParser(string token, EntitlementTokenProperties result) : this((token, Errorable.Success(result)))
{
}
public FakeEntitlementParser(params (string Token, Errorable<NodeEntitlements> Result)[] output)
public FakeTokenPropertyParser(params (string Token, Errorable<EntitlementTokenProperties> Result)[] output)
{
_outputLookup = output.ToDictionary(x => x.Token, x => x.Result);
}
public Errorable<NodeEntitlements> Parse(string token)
public Errorable<EntitlementTokenProperties> Parse(string token)
{
if (!_outputLookup.TryGetValue(token, out var entitlementResult))
{

Просмотреть файл

@ -6,16 +6,16 @@ using Microsoft.Azure.Batch.SoftwareEntitlement.Common;
namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
{
public sealed class FakeEntitlementPropertyProvider : IEntitlementPropertyProvider
public sealed class FakeTokenPropertyProvider : ITokenPropertyProvider
{
public static FakeEntitlementPropertyProvider CreateValid()
public static FakeTokenPropertyProvider CreateValid()
{
var now = DateTimeOffset.Now;
return new FakeEntitlementPropertyProvider
return new FakeTokenPropertyProvider
{
ApplicationIds = Errorable.Success(new[] { "contosoapp" }.AsEnumerable()),
Audience = Errorable.Success("https://audience.region.batch.azure.test"),
EntitlementId = Errorable.Success("entitlement-fbacd5f2-0bce-46db-a374-2682c975d95d"),
TokenId = Errorable.Success("token-fbacd5f2-0bce-46db-a374-2682c975d95d"),
IpAddresses = Errorable.Success(new List<IPAddress> { IPAddress.Parse("127.0.0.1") }.AsEnumerable()),
IssuedAt = Errorable.Success(now),
Issuer = Errorable.Success("https://issuer.region.batch.azure.test"),
@ -29,7 +29,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
public Errorable<string> Audience { get; set; }
public Errorable<string> EntitlementId { get; set; }
public Errorable<string> TokenId { get; set; }
public Errorable<IEnumerable<IPAddress>> IpAddresses { get; set; }
@ -43,22 +43,22 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
public Errorable<string> VirtualMachineId { get; set; }
Errorable<IEnumerable<string>> IEntitlementPropertyProvider.ApplicationIds() => ApplicationIds;
Errorable<IEnumerable<string>> ITokenPropertyProvider.ApplicationIds() => ApplicationIds;
Errorable<string> IEntitlementPropertyProvider.Audience() => Audience;
Errorable<string> ITokenPropertyProvider.Audience() => Audience;
Errorable<string> IEntitlementPropertyProvider.EntitlementId() => EntitlementId;
Errorable<string> ITokenPropertyProvider.TokenId() => TokenId;
Errorable<IEnumerable<IPAddress>> IEntitlementPropertyProvider.IpAddresses() => IpAddresses;
Errorable<IEnumerable<IPAddress>> ITokenPropertyProvider.IpAddresses() => IpAddresses;
Errorable<DateTimeOffset> IEntitlementPropertyProvider.IssuedAt() => IssuedAt;
Errorable<DateTimeOffset> ITokenPropertyProvider.IssuedAt() => IssuedAt;
Errorable<string> IEntitlementPropertyProvider.Issuer() => Issuer;
Errorable<string> ITokenPropertyProvider.Issuer() => Issuer;
Errorable<DateTimeOffset> IEntitlementPropertyProvider.NotAfter() => NotAfter;
Errorable<DateTimeOffset> ITokenPropertyProvider.NotAfter() => NotAfter;
Errorable<DateTimeOffset> IEntitlementPropertyProvider.NotBefore() => NotBefore;
Errorable<DateTimeOffset> ITokenPropertyProvider.NotBefore() => NotBefore;
Errorable<string> IEntitlementPropertyProvider.VirtualMachineId() => VirtualMachineId;
Errorable<string> ITokenPropertyProvider.VirtualMachineId() => VirtualMachineId;
}
}

Просмотреть файл

@ -7,7 +7,7 @@ using Xunit;
namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
{
public class JwtEntitlementParserTests
public class JwtPropertyParserTests
{
// Credentials used for encryption
private readonly EncryptingCredentials _encryptingCredentials;
@ -16,9 +16,9 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
private readonly SigningCredentials _signingCredentials;
// The entitlements used to generate the token
private readonly NodeEntitlements _sourceEntitlements;
private readonly EntitlementTokenProperties _sourceTokenProperties;
public JwtEntitlementParserTests()
public JwtPropertyParserTests()
{
// Hard coded key for unit testing only; actual operation will use a cert
const string plainTextSigningKey = "This is my shared, not so secret, secret that needs to be very long!";
@ -30,38 +30,38 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
var encryptingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(plainTextEncryptionKey));
_encryptingCredentials = new EncryptingCredentials(encryptingKey, "dir", SecurityAlgorithms.Aes256CbcHmacSha512);
_sourceEntitlements = NodeEntitlements.Build(FakeEntitlementPropertyProvider.CreateValid()).Value;
_sourceTokenProperties = EntitlementTokenProperties.Build(FakeTokenPropertyProvider.CreateValid()).Value;
}
private string GenerateToken(NodeEntitlements entitlements)
private string GenerateToken(EntitlementTokenProperties tokenProperties)
{
var generator = new TokenGenerator(NullLogger.Instance, _signingCredentials, _encryptingCredentials);
return generator.Generate(entitlements);
return generator.Generate(tokenProperties);
}
private JwtEntitlementParser CreateParser(string expectedAudience, string expectedIssuer)
private JwtPropertyParser CreateParser(string expectedAudience, string expectedIssuer)
{
return new JwtEntitlementParser(
return new JwtPropertyParser(
expectedAudience,
expectedIssuer,
_signingCredentials.Key,
_encryptingCredentials.Key);
}
public class MalformedToken : JwtEntitlementParserTests
public class MalformedToken : JwtPropertyParserTests
{
[Fact]
public void WhenTokenMalformed_ReturnsError()
{
var entitlements = _sourceEntitlements;
var parser = CreateParser(entitlements.Audience, entitlements.Issuer);
var tokenProperties = _sourceTokenProperties;
var parser = CreateParser(tokenProperties.Audience, tokenProperties.Issuer);
var result = parser.Parse("notarealtoken");
result.HasValue.Should().BeFalse();
result.Errors.Should().Contain(e => e.Contains("not well formed"));
}
}
public class TokenTimeSpan : JwtEntitlementParserTests
public class TokenTimeSpan : JwtPropertyParserTests
{
private readonly TimeSpan _oneWeek = TimeSpan.FromDays(7);
@ -73,11 +73,11 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
[Fact]
public void WhenTokenHasExpired_ReturnsExpectedError()
{
var entitlements = _sourceEntitlements
var tokenProperties = _sourceTokenProperties
.FromInstant(_now - _oneWeek)
.UntilInstant(_now - _oneDay);
var token = GenerateToken(entitlements);
var parser = CreateParser(entitlements.Audience, entitlements.Issuer);
var token = GenerateToken(tokenProperties);
var parser = CreateParser(tokenProperties.Audience, tokenProperties.Issuer);
var result = parser.Parse(token);
result.HasValue.Should().BeFalse();
result.Errors.Should().Contain(e => e.Contains("expired"));
@ -86,18 +86,18 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
[Fact]
public void WhenTokenHasNotYetStarted_ReturnsExpectedError()
{
var entitlements = _sourceEntitlements
var tokenProperties = _sourceTokenProperties
.FromInstant(_now + _oneDay)
.UntilInstant(_now + _oneWeek);
var token = GenerateToken(entitlements);
var parser = CreateParser(entitlements.Audience, entitlements.Issuer);
var token = GenerateToken(tokenProperties);
var parser = CreateParser(tokenProperties.Audience, tokenProperties.Issuer);
var result = parser.Parse(token);
result.HasValue.Should().BeFalse();
result.Errors.Should().Contain(e => e.Contains("will not be valid"));
}
}
public class TokenIssuer : JwtEntitlementParserTests
public class TokenIssuer : JwtPropertyParserTests
{
private readonly string _expectedIssuer = "https://issuer.region.batch.azure.test";
private readonly string _unexpectedIssuer = "https://not-the-expected-issuer.region.batch.azure.test";
@ -105,16 +105,16 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
[Fact]
public void WhenTokenContainsUnexpectedIssuer_ReturnsExpectedError()
{
var entitlements = _sourceEntitlements.WithIssuer(_unexpectedIssuer);
var token = GenerateToken(entitlements);
var parser = CreateParser(entitlements.Audience, _expectedIssuer);
var tokenProperties = _sourceTokenProperties.WithIssuer(_unexpectedIssuer);
var token = GenerateToken(tokenProperties);
var parser = CreateParser(tokenProperties.Audience, _expectedIssuer);
var result = parser.Parse(token);
result.HasValue.Should().BeFalse();
result.Errors.Should().Contain(e => e.Contains("Invalid issuer"));
}
}
public class TokenAudience : JwtEntitlementParserTests
public class TokenAudience : JwtPropertyParserTests
{
private readonly string _expectedAudience = "https://audience.region.batch.azure.test";
private readonly string _unexpectedAudience = "https://not-the-expected-audience.region.batch.azure.test";
@ -122,9 +122,9 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
[Fact]
public void WhenTokenContainsUnexpectedAudience_ReturnsExpectedError()
{
var entitlements = _sourceEntitlements.WithAudience(_unexpectedAudience);
var token = GenerateToken(entitlements);
var parser = CreateParser(_expectedAudience, entitlements.Issuer);
var tokenProperties = _sourceTokenProperties.WithAudience(_unexpectedAudience);
var token = GenerateToken(tokenProperties);
var parser = CreateParser(_expectedAudience, tokenProperties.Issuer);
var result = parser.Parse(token);
result.HasValue.Should().BeFalse();
result.Errors.Should().Contain(e => e.Contains("Invalid audience"));

Просмотреть файл

@ -10,26 +10,26 @@ using Xunit;
namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
{
public class JwtEntitlementPropertyProviderTests
public class JwtPropertyProviderTests
{
// The entitlements used to generate the token
private readonly NodeEntitlements _sourceEntitlements;
private readonly EntitlementTokenProperties _sourceTokenProperties;
// Current time - captured as a member so it doesn't change during a test
private readonly DateTimeOffset _now = DateTimeOffset.Now;
public JwtEntitlementPropertyProviderTests()
public JwtPropertyProviderTests()
{
_sourceEntitlements = NodeEntitlements.Build(FakeEntitlementPropertyProvider.CreateValid()).Value;
_sourceTokenProperties = EntitlementTokenProperties.Build(FakeTokenPropertyProvider.CreateValid()).Value;
}
private static JwtEntitlementPropertyProvider CreatePropertyProvider(NodeEntitlements sourceEntitlements)
private static JwtPropertyProvider CreatePropertyProvider(EntitlementTokenProperties sourceTokenProperties)
{
var generator = new TokenGenerator(NullLogger.Instance);
var tokenString = generator.Generate(sourceEntitlements);
var tokenString = generator.Generate(sourceTokenProperties);
var (principal, token) = ParseToken(tokenString);
return new JwtEntitlementPropertyProvider(principal, token);
return new JwtPropertyProvider(principal, token);
}
private static (ClaimsPrincipal Principal, JwtSecurityToken Token) ParseToken(string tokenString)
@ -56,15 +56,15 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
return (principal, jwt);
}
public class NotBefore : JwtEntitlementPropertyProviderTests
public class NotBefore : JwtPropertyProviderTests
{
[Fact]
public void WhenJwtStillValid_ReturnsSpecifiedValue()
{
var validFrom = _now.AddDays(-1);
var validTo = _now.AddDays(1);
var entitlements = _sourceEntitlements.FromInstant(validFrom).UntilInstant(validTo);
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.FromInstant(validFrom).UntilInstant(validTo);
var provider = CreatePropertyProvider(tokenProperties);
provider.NotBefore().HasValue.Should().BeTrue();
provider.NotBefore().Value.Should().BeCloseTo(validFrom, precision: 1000);
}
@ -74,8 +74,8 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
{
var validFrom = _now.AddDays(1);
var validTo = _now.AddDays(2);
var entitlements = _sourceEntitlements.FromInstant(validFrom).UntilInstant(validTo);
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.FromInstant(validFrom).UntilInstant(validTo);
var provider = CreatePropertyProvider(tokenProperties);
// The property provider is not responsible for validating not-before/not-after.
// It is expected to simply return what is provided in the JWT, which is assumed
@ -85,15 +85,15 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
}
}
public class NotAfter : JwtEntitlementPropertyProviderTests
public class NotAfter : JwtPropertyProviderTests
{
[Fact]
public void WhenJwtStillValid_ReturnsSpecifiedValue()
{
var validFrom = _now.AddDays(-1);
var validTo = _now.AddDays(1);
var entitlements = _sourceEntitlements.FromInstant(validFrom).UntilInstant(validTo);
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.FromInstant(validFrom).UntilInstant(validTo);
var provider = CreatePropertyProvider(tokenProperties);
provider.NotAfter().HasValue.Should().BeTrue();
provider.NotAfter().Value.Should().BeCloseTo(validTo, precision: 1000);
}
@ -103,8 +103,8 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
{
var validFrom = _now.AddDays(-2);
var validTo = _now.AddDays(-1);
var entitlements = _sourceEntitlements.FromInstant(validFrom).UntilInstant(validTo);
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.FromInstant(validFrom).UntilInstant(validTo);
var provider = CreatePropertyProvider(tokenProperties);
// The property provider is not responsible for validating not-before/not-after.
// It is expected to simply return what is provided in the JWT, which is assumed
@ -114,15 +114,15 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
}
}
public class Audience : JwtEntitlementPropertyProviderTests
public class Audience : JwtPropertyProviderTests
{
private readonly string _audience = "http://any.audience";
[Fact]
public void WhenAudienceSpecified_ReturnsSpecifiedValue()
{
var entitlements = _sourceEntitlements.WithAudience(_audience);
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.WithAudience(_audience);
var provider = CreatePropertyProvider(tokenProperties);
// The property provider is not responsible for validating that the audience
// matches an expected value (which is not known at this point).
@ -131,15 +131,15 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
}
}
public class Issuer : JwtEntitlementPropertyProviderTests
public class Issuer : JwtPropertyProviderTests
{
private readonly string _issuer = "http://any.issuer";
[Fact]
public void WhenIssuerSpecified_ReturnsSpecifiedValue()
{
var entitlements = _sourceEntitlements.WithIssuer(_issuer);
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.WithIssuer(_issuer);
var provider = CreatePropertyProvider(tokenProperties);
// The property provider is not responsible for validating that the issuer
// matches an expected value (which is not known at this point).
@ -148,41 +148,41 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
}
}
public class IssuedAt : JwtEntitlementPropertyProviderTests
public class IssuedAt : JwtPropertyProviderTests
{
private readonly DateTimeOffset _inPast = new DateTime(2016, 1, 1);
[Fact]
public void WhenIssueDateSpecified_ReturnsSpecifiedValue()
{
var entitlements = _sourceEntitlements.WithIssuedAt(_inPast);
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.WithIssuedAt(_inPast);
var provider = CreatePropertyProvider(tokenProperties);
provider.IssuedAt().HasValue.Should().BeTrue();
provider.IssuedAt().Value.Should().Be(_inPast);
}
}
public class VirtualMachineIdentifier : JwtEntitlementPropertyProviderTests
public class VirtualMachineIdentifier : JwtPropertyProviderTests
{
[Fact]
public void WhenIdentifierIncluded_ReturnsSpecifiedValue()
{
var provider = CreatePropertyProvider(_sourceEntitlements);
var provider = CreatePropertyProvider(_sourceTokenProperties);
provider.VirtualMachineId().HasValue.Should().BeTrue();
provider.VirtualMachineId().Value.Should().Be(_sourceEntitlements.VirtualMachineId);
provider.VirtualMachineId().Value.Should().Be(_sourceTokenProperties.VirtualMachineId);
}
[Fact]
public void WhenIdentifierOmitted_ReturnsNull()
{
var entitlements = _sourceEntitlements.WithVirtualMachineId(null);
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.WithVirtualMachineId(null);
var provider = CreatePropertyProvider(tokenProperties);
provider.VirtualMachineId().HasValue.Should().BeTrue();
provider.VirtualMachineId().Value.Should().BeNull();
}
}
public class Applications : JwtEntitlementPropertyProviderTests
public class Applications : JwtPropertyProviderTests
{
private readonly string _app1 = "contosofinance";
private readonly string _app2 = "contosoit";
@ -191,8 +191,8 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
[Fact]
public void WhenSingleApplicationSpecified_ReturnsSpecifiedValue()
{
var entitlements = _sourceEntitlements.WithApplications(_app1);
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.WithApplications(_app1);
var provider = CreatePropertyProvider(tokenProperties);
provider.ApplicationIds().HasValue.Should().BeTrue();
provider.ApplicationIds().Value.Single().Should().Be(_app1);
}
@ -200,23 +200,23 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
[Fact]
public void WhenMultipleApplicationsSpecified_ReturnsAllSpecifiedValues()
{
var entitlements = _sourceEntitlements.WithApplications(_app1, _app2, _app3);
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.WithApplications(_app1, _app2, _app3);
var provider = CreatePropertyProvider(tokenProperties);
provider.ApplicationIds().HasValue.Should().BeTrue();
provider.ApplicationIds().Value.Should().BeEquivalentTo(new[] { _app1, _app2, _app3 });
provider.ApplicationIds().Value.Should().BeEquivalentTo(_app1, _app2, _app3);
}
[Fact]
public void WhenNoApplicationsSpecified_ReturnsError()
{
var entitlements = _sourceEntitlements.WithApplications();
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.WithApplications();
var provider = CreatePropertyProvider(tokenProperties);
provider.ApplicationIds().HasValue.Should().BeFalse();
provider.ApplicationIds().Errors.Should().Contain("No application id claims found in token.");
}
}
public class IpAddresses : JwtEntitlementPropertyProviderTests
public class IpAddresses : JwtPropertyProviderTests
{
private readonly IPAddress _addr1 = IPAddress.Parse("203.0.113.42");
private readonly IPAddress _addr2 = IPAddress.Parse("203.0.113.43");
@ -225,8 +225,8 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
[Fact]
public void WhenSingleIpAddressSpecified_ReturnsSpecifiedValue()
{
var entitlements = _sourceEntitlements.WithIpAddresses(_addr1);
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.WithIpAddresses(_addr1);
var provider = CreatePropertyProvider(tokenProperties);
provider.IpAddresses().HasValue.Should().BeTrue();
provider.IpAddresses().Value.Single().Should().Be(_addr1);
}
@ -234,39 +234,39 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
[Fact]
public void WhenMultipleIpAddressesSpecified_ReturnsAllSpecifiedValues()
{
var entitlements = _sourceEntitlements.WithIpAddresses(_addr1, _addr2, _addr3);
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.WithIpAddresses(_addr1, _addr2, _addr3);
var provider = CreatePropertyProvider(tokenProperties);
provider.IpAddresses().HasValue.Should().BeTrue();
provider.IpAddresses().Value.Should().BeEquivalentTo(new[] { _addr1, _addr2, _addr3 });
provider.IpAddresses().Value.Should().BeEquivalentTo(_addr1, _addr2, _addr3);
}
[Fact]
public void WhenNoIpAddressesSpecified_ReturnsNoValues()
{
var entitlements = _sourceEntitlements.WithIpAddresses();
var provider = CreatePropertyProvider(entitlements);
var tokenProperties = _sourceTokenProperties.WithIpAddresses();
var provider = CreatePropertyProvider(tokenProperties);
provider.IpAddresses().HasValue.Should().BeTrue();
provider.IpAddresses().Value.Should().BeEmpty();
}
}
public class Identifier : JwtEntitlementPropertyProviderTests
public class Identifier : JwtPropertyProviderTests
{
[Fact]
public void WhenIdentifierSpecified_ReturnsSpecifiedValue()
{
var provider = CreatePropertyProvider(_sourceEntitlements);
provider.EntitlementId().HasValue.Should().BeTrue();
provider.EntitlementId().Value.Should().Be(_sourceEntitlements.Identifier);
var provider = CreatePropertyProvider(_sourceTokenProperties);
provider.TokenId().HasValue.Should().BeTrue();
provider.TokenId().Value.Should().Be(_sourceTokenProperties.Identifier);
}
[Fact]
public void WhenIdentifierOmitted_ReturnsError()
{
var entitlements = _sourceEntitlements.WithIdentifier(null);
var provider = CreatePropertyProvider(entitlements);
provider.EntitlementId().HasValue.Should().BeFalse();
provider.EntitlementId().Errors.Should().Contain(e => e.Contains("identifier"));
var tokenProperties = _sourceTokenProperties.WithIdentifier(null);
var provider = CreatePropertyProvider(tokenProperties);
provider.TokenId().HasValue.Should().BeFalse();
provider.TokenId().Errors.Should().Contain(e => e.Contains("identifier"));
}
}
}

Просмотреть файл

@ -64,12 +64,12 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
}
[Fact]
public void GivenNullEntitlement_ThrowsArgumentNullException()
public void GivenNullTokenProperties_ThrowsArgumentNullException()
{
var exception =
Assert.Throws<ArgumentNullException>(
() => _generator.Generate(null));
exception.ParamName.Should().Be("entitlements");
exception.ParamName.Should().Be("tokenProperties");
}
}
}

Просмотреть файл

@ -14,13 +14,13 @@ using Xunit;
namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
{
public class EntitlementVerifierTests
public class TokenVerifierTests
{
// An entitlements object representing a complete set of claims
private readonly NodeEntitlements _completeEntitlement;
// An token properties object representing a complete set of claims
private readonly EntitlementTokenProperties _completeTokenProperties;
// An entitlement verification request which is valid for the above entitlement
private readonly EntitlementVerificationRequest _validEntitlementRequest;
private readonly TokenVerificationRequest _validVerificationRequest;
// Logger that does nothing
private readonly ILogger _nullLogger = NullLogger.Instance;
@ -34,7 +34,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
// Used to look up values in a fake entitlement parser
private readonly string _testToken = "testtoken";
public EntitlementVerifierTests()
public TokenVerifierTests()
{
// Hard coded key for unit testing only; actual operation will use a cert
const string plainTextSigningKey = "This is my shared, not so secret, secret that needs to be very long!";
@ -46,51 +46,51 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
var encryptingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(plainTextEncryptionKey));
_encryptingCredentials = new EncryptingCredentials(encryptingKey, "dir", SecurityAlgorithms.Aes256CbcHmacSha512);
_completeEntitlement = NodeEntitlements.Build(FakeEntitlementPropertyProvider.CreateValid()).Value;
_validEntitlementRequest = new EntitlementVerificationRequest(
_completeEntitlement.Applications.First(),
_completeEntitlement.IpAddresses.First());
_completeTokenProperties = EntitlementTokenProperties.Build(FakeTokenPropertyProvider.CreateValid()).Value;
_validVerificationRequest = new TokenVerificationRequest(
_completeTokenProperties.Applications.First(),
_completeTokenProperties.IpAddresses.First());
}
private string CreateSignedEncryptedJwtToken(NodeEntitlements entitlement)
=> CreateJwtToken(entitlement, _signingCredentials, _encryptingCredentials);
private string CreateSignedEncryptedJwtToken(EntitlementTokenProperties tokenProperties)
=> CreateJwtToken(tokenProperties, _signingCredentials, _encryptingCredentials);
private string CreateJwtToken(
NodeEntitlements entitlement,
EntitlementTokenProperties tokenProperties,
SigningCredentials signingCredentials,
EncryptingCredentials encryptingCredentials)
{
var generator = new TokenGenerator(_nullLogger, signingCredentials, encryptingCredentials);
return generator.Generate(entitlement);
return generator.Generate(tokenProperties);
}
private EntitlementVerifier CreateSignedEncryptedJwtEntitlementVerifier(
private TokenVerifier CreateSignedEncryptedJwtTokenVerifier(
string expectedAudience,
string expectedIssuer)
=> CreateJwtEntitlementVerifier(expectedAudience, expectedIssuer, _signingCredentials.Key, _encryptingCredentials.Key);
=> CreateJwtTokenVerifier(expectedAudience, expectedIssuer, _signingCredentials.Key, _encryptingCredentials.Key);
private EntitlementVerifier CreateJwtEntitlementVerifier(
private TokenVerifier CreateJwtTokenVerifier(
string expectedAudience,
string expectedIssuer,
SecurityKey signingKey,
SecurityKey encryptingKey)
{
var parser = new JwtEntitlementParser(expectedAudience, expectedIssuer, signingKey, encryptingKey);
return new EntitlementVerifier(parser);
var parser = new JwtPropertyParser(expectedAudience, expectedIssuer, signingKey, encryptingKey);
return new TokenVerifier(parser);
}
public class Verify : EntitlementVerifierTests
public class Verify : TokenVerifierTests
{
[Fact]
public void WhenTokenIsNull_ThrowsException()
{
var verifier = new EntitlementVerifier(new FakeEntitlementParser());
var verifier = new TokenVerifier(new FakeTokenPropertyParser());
Assert.Throws<ArgumentNullException>(
() => verifier.Verify(_validEntitlementRequest, null));
() => verifier.Verify(_validVerificationRequest, null));
}
}
public class VerifyApplication : EntitlementVerifierTests
public class VerifyApplication : TokenVerifierTests
{
private readonly string _otherApp1 = "contosoit";
private readonly string _otherApp2 = "contosohr";
@ -98,59 +98,59 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
[Fact]
public void WhenEntitlementContainsNoApplications_ReturnsError()
{
var entitlement = _completeEntitlement.WithApplications();
var parser = new FakeEntitlementParser(_testToken, entitlement);
var verifier = new EntitlementVerifier(parser);
var result = verifier.Verify(_validEntitlementRequest, _testToken);
var tokenProperties = _completeTokenProperties.WithApplications();
var parser = new FakeTokenPropertyParser(_testToken, tokenProperties);
var verifier = new TokenVerifier(parser);
var result = verifier.Verify(_validVerificationRequest, _testToken);
result.HasValue.Should().BeFalse();
result.Errors.Should().Contain(e => e.Contains(_validEntitlementRequest.ApplicationId));
result.Errors.Should().Contain(e => e.Contains(_validVerificationRequest.ApplicationId));
}
[Fact]
public void WhenEntitlementContainsOnlyTheRequestedApplication_ReturnsSuccess()
{
var entitlement = _completeEntitlement.WithApplications(_validEntitlementRequest.ApplicationId);
var parser = new FakeEntitlementParser(_testToken, entitlement);
var verifier = new EntitlementVerifier(parser);
var result = verifier.Verify(_validEntitlementRequest, _testToken);
var tokenProperties = _completeTokenProperties.WithApplications(_validVerificationRequest.ApplicationId);
var parser = new FakeTokenPropertyParser(_testToken, tokenProperties);
var verifier = new TokenVerifier(parser);
var result = verifier.Verify(_validVerificationRequest, _testToken);
result.HasValue.Should().BeTrue();
}
[Fact]
public void WhenEntitlementContainsOnlyADifferentApplication_ReturnsError()
{
var entitlement = _completeEntitlement.WithApplications(_otherApp1);
var parser = new FakeEntitlementParser(_testToken, entitlement);
var verifier = new EntitlementVerifier(parser);
var result = verifier.Verify(_validEntitlementRequest, _testToken);
var tokenProperties = _completeTokenProperties.WithApplications(_otherApp1);
var parser = new FakeTokenPropertyParser(_testToken, tokenProperties);
var verifier = new TokenVerifier(parser);
var result = verifier.Verify(_validVerificationRequest, _testToken);
result.HasValue.Should().BeFalse();
result.Errors.Should().Contain(e => e.Contains(_validEntitlementRequest.ApplicationId));
result.Errors.Should().Contain(e => e.Contains(_validVerificationRequest.ApplicationId));
}
[Fact]
public void WhenEntitlementContainsMultipleApplicationsButNotTheRequestedApplication_ReturnsError()
{
var entitlement = _completeEntitlement.WithApplications(_otherApp1, _otherApp2);
var parser = new FakeEntitlementParser(_testToken, entitlement);
var verifier = new EntitlementVerifier(parser);
var result = verifier.Verify(_validEntitlementRequest, _testToken);
var tokenProperties = _completeTokenProperties.WithApplications(_otherApp1, _otherApp2);
var parser = new FakeTokenPropertyParser(_testToken, tokenProperties);
var verifier = new TokenVerifier(parser);
var result = verifier.Verify(_validVerificationRequest, _testToken);
result.HasValue.Should().BeFalse();
result.Errors.Should().Contain(e => e.Contains(_validEntitlementRequest.ApplicationId));
result.Errors.Should().Contain(e => e.Contains(_validVerificationRequest.ApplicationId));
}
[Fact]
public void WhenEntitlementContainsMultipleApplicationsIncludingTheRequestedApplication_ReturnsSuccess()
{
var entitlement = _completeEntitlement.WithApplications(
_validEntitlementRequest.ApplicationId, _otherApp1, _otherApp2);
var parser = new FakeEntitlementParser(_testToken, entitlement);
var verifier = new EntitlementVerifier(parser);
var result = verifier.Verify(_validEntitlementRequest, _testToken);
var tokenProperties = _completeTokenProperties.WithApplications(
_validVerificationRequest.ApplicationId, _otherApp1, _otherApp2);
var parser = new FakeTokenPropertyParser(_testToken, tokenProperties);
var verifier = new TokenVerifier(parser);
var result = verifier.Verify(_validVerificationRequest, _testToken);
result.HasValue.Should().BeTrue();
}
}
public class VerifyIpAddress : EntitlementVerifierTests
public class VerifyIpAddress : TokenVerifierTests
{
private readonly IPAddress _otherAddress1 = IPAddress.Parse("203.0.113.42");
private readonly IPAddress _otherAddress2 = IPAddress.Parse("203.0.113.43");
@ -158,54 +158,54 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
[Fact]
public void WhenEntitlementContainsNoIpAddresses_ReturnsError()
{
var entitlement = _completeEntitlement.WithIpAddresses();
var parser = new FakeEntitlementParser(_testToken, entitlement);
var verifier = new EntitlementVerifier(parser);
var result = verifier.Verify(_validEntitlementRequest, _testToken);
var tokenProperties = _completeTokenProperties.WithIpAddresses();
var parser = new FakeTokenPropertyParser(_testToken, tokenProperties);
var verifier = new TokenVerifier(parser);
var result = verifier.Verify(_validVerificationRequest, _testToken);
result.HasValue.Should().BeFalse();
result.Errors.Should().Contain(e => e.Contains(_validEntitlementRequest.IpAddress.ToString()));
result.Errors.Should().Contain(e => e.Contains(_validVerificationRequest.IpAddress.ToString()));
}
[Fact]
public void WhenEntitlementContainsOnlyTheRequestedIpAddress_ReturnsSuccess()
{
var entitlement = _completeEntitlement.WithIpAddresses(_validEntitlementRequest.IpAddress);
var parser = new FakeEntitlementParser(_testToken, entitlement);
var verifier = new EntitlementVerifier(parser);
var result = verifier.Verify(_validEntitlementRequest, _testToken);
var tokenProperties = _completeTokenProperties.WithIpAddresses(_validVerificationRequest.IpAddress);
var parser = new FakeTokenPropertyParser(_testToken, tokenProperties);
var verifier = new TokenVerifier(parser);
var result = verifier.Verify(_validVerificationRequest, _testToken);
result.HasValue.Should().BeTrue();
}
[Fact]
public void WhenEntitlementContainsOnlyADifferentIpAddress_ReturnsError()
{
var entitlement = _completeEntitlement.WithIpAddresses(_otherAddress1);
var parser = new FakeEntitlementParser(_testToken, entitlement);
var verifier = new EntitlementVerifier(parser);
var result = verifier.Verify(_validEntitlementRequest, _testToken);
var tokenProperties = _completeTokenProperties.WithIpAddresses(_otherAddress1);
var parser = new FakeTokenPropertyParser(_testToken, tokenProperties);
var verifier = new TokenVerifier(parser);
var result = verifier.Verify(_validVerificationRequest, _testToken);
result.HasValue.Should().BeFalse();
result.Errors.Should().Contain(e => e.Contains(_validEntitlementRequest.IpAddress.ToString()));
result.Errors.Should().Contain(e => e.Contains(_validVerificationRequest.IpAddress.ToString()));
}
[Fact]
public void WhenEntitlementContainsMultipleIpAddressesButNotTheRequestedOne_ReturnsError()
{
var entitlement = _completeEntitlement.WithIpAddresses(_otherAddress1, _otherAddress2);
var parser = new FakeEntitlementParser(_testToken, entitlement);
var verifier = new EntitlementVerifier(parser);
var result = verifier.Verify(_validEntitlementRequest, _testToken);
var tokenProperties = _completeTokenProperties.WithIpAddresses(_otherAddress1, _otherAddress2);
var parser = new FakeTokenPropertyParser(_testToken, tokenProperties);
var verifier = new TokenVerifier(parser);
var result = verifier.Verify(_validVerificationRequest, _testToken);
result.HasValue.Should().BeFalse();
result.Errors.Should().Contain(e => e.Contains(_validEntitlementRequest.IpAddress.ToString()));
result.Errors.Should().Contain(e => e.Contains(_validVerificationRequest.IpAddress.ToString()));
}
[Fact]
public void WhenEntitlementContainsMultipleIpAddressesIncludingTheRequestedOne_ReturnsSuccess()
{
var entitlement = _completeEntitlement.WithIpAddresses(
_validEntitlementRequest.IpAddress, _otherAddress1, _otherAddress2);
var parser = new FakeEntitlementParser(_testToken, entitlement);
var verifier = new EntitlementVerifier(parser);
var result = verifier.Verify(_validEntitlementRequest, _testToken);
var tokenProperties = _completeTokenProperties.WithIpAddresses(
_validVerificationRequest.IpAddress, _otherAddress1, _otherAddress2);
var parser = new FakeTokenPropertyParser(_testToken, tokenProperties);
var verifier = new TokenVerifier(parser);
var result = verifier.Verify(_validVerificationRequest, _testToken);
result.HasValue.Should().BeTrue();
}
}
@ -213,14 +213,14 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
/// <summary>
/// Tests to check that enforcement works end to end with both signing and encryption
/// </summary>
public class WithSigningAndEncryption : EntitlementVerifierTests
public class WithSigningAndEncryption : TokenVerifierTests
{
[Fact]
public void GivenValidEntitlement_ReturnsSuccess()
{
var verifier = CreateSignedEncryptedJwtEntitlementVerifier(_completeEntitlement.Audience, _completeEntitlement.Issuer);
var token = CreateSignedEncryptedJwtToken(_completeEntitlement);
var result = verifier.Verify(_validEntitlementRequest, token);
var verifier = CreateSignedEncryptedJwtTokenVerifier(_completeTokenProperties.Audience, _completeTokenProperties.Issuer);
var token = CreateSignedEncryptedJwtToken(_completeTokenProperties);
var result = verifier.Verify(_validVerificationRequest, token);
result.HasValue.Should().BeTrue();
}
}
@ -228,20 +228,20 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
/// <summary>
/// Tests to check that enforcement works end to end with no signing key
/// </summary>
public class WithEncryptionOnly : EntitlementVerifierTests
public class WithEncryptionOnly : TokenVerifierTests
{
[Fact]
public void GivenValidEntitlement_ReturnsSuccess()
{
var verifier = CreateJwtEntitlementVerifier(
_completeEntitlement.Audience,
_completeEntitlement.Issuer,
var verifier = CreateJwtTokenVerifier(
_completeTokenProperties.Audience,
_completeTokenProperties.Issuer,
signingKey: null,
encryptingKey: _encryptingCredentials.Key);
var token = CreateJwtToken(_completeEntitlement, signingCredentials: null, encryptingCredentials: _encryptingCredentials);
var token = CreateJwtToken(_completeTokenProperties, signingCredentials: null, encryptingCredentials: _encryptingCredentials);
var result = verifier.Verify(_validEntitlementRequest, token);
var result = verifier.Verify(_validVerificationRequest, token);
result.HasValue.Should().BeTrue();
}
}
@ -249,20 +249,20 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
/// <summary>
/// Tests to check that enforcement works end to end with no encryption key
/// </summary>
public class WithSigningOnly : EntitlementVerifierTests
public class WithSigningOnly : TokenVerifierTests
{
[Fact]
public void GivenValidEntitlement_ReturnsSuccess()
{
var verifier = CreateJwtEntitlementVerifier(
_completeEntitlement.Audience,
_completeEntitlement.Issuer,
var verifier = CreateJwtTokenVerifier(
_completeTokenProperties.Audience,
_completeTokenProperties.Issuer,
signingKey: _signingCredentials.Key,
encryptingKey: null);
var token = CreateJwtToken(_completeEntitlement, signingCredentials: _signingCredentials, encryptingCredentials: null);
var token = CreateJwtToken(_completeTokenProperties, signingCredentials: _signingCredentials, encryptingCredentials: null);
var result = verifier.Verify(_validEntitlementRequest, token);
var result = verifier.Verify(_validVerificationRequest, token);
result.HasValue.Should().BeTrue();
}
}
@ -270,25 +270,25 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
/// <summary>
/// Tests to check that enforcement works end to end without signing or encryption
/// </summary>
public class WithoutSigningOrEncryption : EntitlementVerifierTests
public class WithoutSigningOrEncryption : TokenVerifierTests
{
[Fact]
public void GivenValidEntitlement_ReturnsSuccess()
{
var verifier = CreateJwtEntitlementVerifier(
_completeEntitlement.Audience,
_completeEntitlement.Issuer,
var verifier = CreateJwtTokenVerifier(
_completeTokenProperties.Audience,
_completeTokenProperties.Issuer,
signingKey: null,
encryptingKey: null);
var token = CreateJwtToken(_completeEntitlement, signingCredentials: null, encryptingCredentials: null);
var token = CreateJwtToken(_completeTokenProperties, signingCredentials: null, encryptingCredentials: null);
var result = verifier.Verify(_validEntitlementRequest, token);
var result = verifier.Verify(_validVerificationRequest, token);
result.HasValue.Should().BeTrue();
}
}
public class WithCertificates : EntitlementVerifierTests
public class WithCertificates : TokenVerifierTests
{
[Theory(Skip = "Specify a certificate thumbprint in TestCaseKeys() to enable this test.")]
[MemberData(nameof(TestCaseKeys))]
@ -297,14 +297,14 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
// Arrange
var signingCredentials = new SigningCredentials(key, SecurityAlgorithms.RsaSha512Signature);
var generator = new TokenGenerator(_nullLogger, signingCredentials, encryptingCredentials: null);
var verifier = CreateJwtEntitlementVerifier(
_completeEntitlement.Audience,
_completeEntitlement.Issuer,
var verifier = CreateJwtTokenVerifier(
_completeTokenProperties.Audience,
_completeTokenProperties.Issuer,
signingKey : key,
encryptingKey: null);
// Act
var token = generator.Generate(_completeEntitlement);
var result = verifier.Verify(_validEntitlementRequest, token);
var token = generator.Generate(_completeTokenProperties);
var result = verifier.Verify(_validVerificationRequest, token);
// Assert
result.HasValue.Should().BeTrue();
result.Errors.Should().BeEmpty();
@ -317,14 +317,14 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
// Arrange
var encryptingCredentials = new EncryptingCredentials(key, SecurityAlgorithms.RsaOAEP, SecurityAlgorithms.Aes256CbcHmacSha512);
var generator = new TokenGenerator(_nullLogger, signingCredentials: null, encryptingCredentials: encryptingCredentials);
var verifier = CreateJwtEntitlementVerifier(
_completeEntitlement.Audience,
_completeEntitlement.Issuer,
var verifier = CreateJwtTokenVerifier(
_completeTokenProperties.Audience,
_completeTokenProperties.Issuer,
signingKey: null,
encryptingKey: key);
// Act
var token = generator.Generate(_completeEntitlement);
var result = verifier.Verify(_validEntitlementRequest, token);
var token = generator.Generate(_completeTokenProperties);
var result = verifier.Verify(_validVerificationRequest, token);
// Assert
result.HasValue.Should().BeTrue();
result.Errors.Should().BeEmpty();

Просмотреть файл

@ -7,12 +7,12 @@ using Xunit;
namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
{
public class CommandLineEntitlementPropertyProviderTests
public class CommandLineTokenPropertyProviderTests
{
// An empty set of command line arguments for testing
private readonly GenerateCommandLine _commandLine = new GenerateCommandLine();
public class Constructor : CommandLineEntitlementPropertyProviderTests
public class Constructor : CommandLineTokenPropertyProviderTests
{
[Fact]
public void GivenNullCommandLine_ThrowsArgumentNullException()
@ -24,7 +24,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
}
}
public class VirtualMachineIdProperty : CommandLineEntitlementPropertyProviderTests
public class VirtualMachineIdProperty : CommandLineTokenPropertyProviderTests
{
const string virtualMachineId = "virtualMachine";
@ -61,7 +61,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
}
}
public class NotBeforeProperty : CommandLineEntitlementPropertyProviderTests
public class NotBeforeProperty : CommandLineTokenPropertyProviderTests
{
private readonly string _validNotBefore =
DateTimeOffset.Now.ToString(TimestampParser.ExpectedFormat, CultureInfo.InvariantCulture);
@ -101,7 +101,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
}
}
public class NotAfterProperty : CommandLineEntitlementPropertyProviderTests
public class NotAfterProperty : CommandLineTokenPropertyProviderTests
{
private readonly string _validNotAfter =
DateTimeOffset.Now.AddDays(7).ToString(TimestampParser.ExpectedFormat, CultureInfo.InvariantCulture);
@ -141,7 +141,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
}
}
public class AudienceProperty : CommandLineEntitlementPropertyProviderTests
public class AudienceProperty : CommandLineTokenPropertyProviderTests
{
private readonly string _audience = "https://account.region.batch.azure.test";
@ -162,7 +162,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
}
}
public class ApplicationsProperty : CommandLineEntitlementPropertyProviderTests
public class ApplicationsProperty : CommandLineTokenPropertyProviderTests
{
private const string ContosoHrApp = "contosoHR";
private const string ContosoItApp = "contosoIT";
@ -208,7 +208,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
}
}
public class AddressesProperty : CommandLineEntitlementPropertyProviderTests
public class AddressesProperty : CommandLineTokenPropertyProviderTests
{
// sample IPAddresses to use for testing (sample addresses as per RFC5735)
private readonly IPAddress _addressA = IPAddress.Parse("203.0.113.46");
@ -256,7 +256,7 @@ namespace Microsoft.Azure.Batch.SoftwareEntitlement.Tests
}
}
public class IssuerProperty : CommandLineEntitlementPropertyProviderTests
public class IssuerProperty : CommandLineTokenPropertyProviderTests
{
private readonly string _issuer = "https://account.region.batch.azure.test";