Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Adding RBAC support for provisioning SDK #2262

Merged
merged 11 commits into from
Jan 10, 2022
27 changes: 27 additions & 0 deletions provisioning/service/src/Auth/ProvisioningSasCredential.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Azure;
using Microsoft.Azure.Devices.Common.Service.Auth;

namespace Microsoft.Azure.Devices.Provisioning.Service.Auth
{
/// <summary>
/// Allows authentication to the API using a Shared Access Key provided by custom implementation.
/// The PnP client is auto generated from swagger and needs to implement a specific class to pass to the protocol layer
/// unlike the rest of the clients which are hand-written. So, this implementation for authentication is specific to digital twin (PnP).
/// </summary>
internal class ProvisioningSasCredential: IAuthorizationHeaderProvider
dylanbulfinMS marked this conversation as resolved.
Show resolved Hide resolved
{
private readonly AzureSasCredential _azureSasCredential;

public ProvisioningSasCredential(AzureSasCredential azureSasCredential)
{
_azureSasCredential = azureSasCredential;
}

public string GetAuthorizationHeader()
{
return _azureSasCredential.Signature;
}
}
}
43 changes: 43 additions & 0 deletions provisioning/service/src/Auth/ProvisioningTokenCredential.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Threading;
using Azure.Core;
using Microsoft.Azure.Devices.Common.Service.Auth;

namespace Microsoft.Azure.Devices.Provisioning.Service.Auth
{
/// <summary>
/// Allows authentication to the API using a JWT token generated for Azure active directory.
/// The PnP client is auto generated from swagger and needs to implement a specific class to pass to the protocol layer
/// unlike the rest of the clients which are hand-written. so, this implementation for authentication is specific to digital twin (PnP).
/// </summary>
internal class ProvisioningTokenCredential : IAuthorizationHeaderProvider
dylanbulfinMS marked this conversation as resolved.
Show resolved Hide resolved
{
private readonly TokenCredential _credential;
private readonly object _tokenLock = new object();
private AccessToken? _cachedAccessToken;

public ProvisioningTokenCredential(TokenCredential credential)
{
_credential = credential;
}

// The HTTP protocol uses this method to get the bearer token for authentication.
public string GetAuthorizationHeader()
{
lock (_tokenLock)
{
// A new token is generated if it is the first time or the cached token is close to expiry.
if (!_cachedAccessToken.HasValue
|| TokenHelper.IsCloseToExpiry(_cachedAccessToken.Value.ExpiresOn))
{
_cachedAccessToken = _credential.GetToken(
new TokenRequestContext(new string[] { "https://azure-devices-provisioning.net/.default" }),
new CancellationToken());
}
}

return $"Bearer {_cachedAccessToken.Value.Token}";
}
}
}
21 changes: 21 additions & 0 deletions provisioning/service/src/Auth/TokenHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;

namespace Microsoft.Azure.Devices.Provisioning.Service.Auth
{
internal static class TokenHelper
{
/// <summary>
/// Determines if the given token expiry date time is close to expiry. The date and time is
/// considered close to expiry if it has less than 10 minutes relative to the current time.
/// </summary>
/// <param name="expiry">The token expiration date and time.</param>
/// <returns>True if the token expiry has less than 10 minutes relative to the current time, otherwise false.</returns>
public static bool IsCloseToExpiry(DateTimeOffset expiry)
{
TimeSpan timeToExpiry = expiry - DateTimeOffset.UtcNow;
return timeToExpiry.TotalMinutes < 10;
}
}
}
5 changes: 3 additions & 2 deletions provisioning/service/src/Manager/EnrollmentGroupManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ await contractApiHttp.RequestAsync(
}

internal static Query CreateQuery(
ServiceConnectionString provisioningConnectionString,
string hostName,
IAuthorizationHeaderProvider headerProvider,
QuerySpecification querySpecification,
HttpTransportSettings httpTransportSettings,
CancellationToken cancellationToken,
Expand All @@ -128,7 +129,7 @@ internal static Query CreateQuery(

/* SRS_ENROLLMENT_GROUP_MANAGER_28_015: [The CreateQuery shall return a new Query for EnrollmentGroup.] */

return new Query(provisioningConnectionString, ServiceName, querySpecification, httpTransportSettings, pageSize, cancellationToken);
return new Query(hostName, headerProvider, ServiceName, querySpecification, httpTransportSettings, pageSize, cancellationToken);
}

private static Uri GetEnrollmentUri(string enrollmentGroupId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ await contractApiHttp.RequestAsync(
}

internal static Query CreateQuery(
ServiceConnectionString provisioningConnectionString,
string hostName,
IAuthorizationHeaderProvider headerProvider,
QuerySpecification querySpecification,
HttpTransportSettings httpTransportSettings,
CancellationToken cancellationToken,
Expand All @@ -168,7 +169,7 @@ internal static Query CreateQuery(
}

/* SRS_INDIVIDUAL_ENROLLMENT_MANAGER_21_015: [The CreateQuery shall return a new Query for IndividualEnrollments.] */
return new Query(provisioningConnectionString, ServiceName, querySpecification, httpTransportSettings, pageSize, cancellationToken);
return new Query(hostName, headerProvider, ServiceName, querySpecification, httpTransportSettings, pageSize, cancellationToken);
}

private static Uri GetEnrollmentUri(string registrationId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ await contractApiHttp.RequestAsync(
[SuppressMessage("Microsoft.Design", "CA1068",
Justification = "Public API cannot change parameter order.")]
internal static Query CreateEnrollmentGroupQuery(
ServiceConnectionString provisioningConnectionString,
string hostName,
IAuthorizationHeaderProvider headerProvider,
QuerySpecification querySpecification,
HttpTransportSettings httpTransportSettings,
CancellationToken cancellationToken,
Expand All @@ -102,7 +103,8 @@ internal static Query CreateEnrollmentGroupQuery(

/* SRS_REGISTRATION_STATUS_MANAGER_28_010: [The CreateQuery shall return a new Query for DeviceRegistrationState.] */
return new Query(
provisioningConnectionString,
hostName,
headerProvider,
GetGetDeviceRegistrationStatus(enrollmentGroupId),
querySpecification,
httpTransportSettings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Azure.Core" Version="1.9.0" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
Loading