Fix docker and store PK in KeyVault only (#27)
-The private key is now only stored in Key Vault. Key generation is back to service, as it slows down operation quite a bit and enforces delete rights for an Approver. -Fix the docker builds and according build settings -Other improvements: Use only a single CosmosDB collection (cost) -license update -CA certs can contain a CRL distribution point (however service side doesn't support it)
This commit is contained in:
Родитель
62198c68cd
Коммит
d4e5505bca
15
.travis.yml
15
.travis.yml
|
@ -1,15 +0,0 @@
|
|||
language: csharp
|
||||
mono: none
|
||||
dotnet: 2.1
|
||||
os: linux
|
||||
sudo: false
|
||||
dist: trusty
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
packages:
|
||||
install:
|
||||
script:
|
||||
- dotnet restore
|
||||
- dotnet build -c Debug
|
||||
- dotnet build -c Release
|
|
@ -7,7 +7,7 @@ WORKDIR /src
|
|||
COPY src/Microsoft.Azure.IIoT.OpcUa.Services.Vault.csproj src/
|
||||
COPY NuGet.Config NuGet.Config
|
||||
RUN dotnet restore --configfile NuGet.Config -nowarn:msb3202,nu1503 src/Microsoft.Azure.IIoT.OpcUa.Services.Vault.csproj
|
||||
COPY . .
|
||||
COPY src/ src/
|
||||
WORKDIR /src/src
|
||||
RUN dotnet build Microsoft.Azure.IIoT.OpcUa.Services.Vault.csproj -c Release -o /app
|
||||
|
|
@ -7,7 +7,7 @@ WORKDIR /src
|
|||
COPY src/Microsoft.Azure.IIoT.OpcUa.Services.Vault.csproj src/
|
||||
COPY NuGet.Config NuGet.Config
|
||||
RUN dotnet restore --configfile NuGet.Config -nowarn:msb3202,nu1503 src/Microsoft.Azure.IIoT.OpcUa.Services.Vault.csproj
|
||||
COPY . .
|
||||
COPY src/ src/
|
||||
WORKDIR /src/src
|
||||
RUN dotnet build Microsoft.Azure.IIoT.OpcUa.Services.Vault.csproj -c Release -o /app
|
||||
|
|
@ -7,7 +7,7 @@ WORKDIR /src
|
|||
COPY src/Microsoft.Azure.IIoT.OpcUa.Services.Vault.csproj src/
|
||||
COPY NuGet.Config NuGet.Config
|
||||
RUN dotnet restore --configfile NuGet.Config -nowarn:msb3202,nu1503 src/Microsoft.Azure.IIoT.OpcUa.Services.Vault.csproj
|
||||
COPY . .
|
||||
COPY src/ src/
|
||||
WORKDIR /src/src
|
||||
RUN dotnet build Microsoft.Azure.IIoT.OpcUa.Services.Vault.csproj -c Release -o /app
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 56310
|
||||
EXPOSE 44342
|
||||
|
||||
FROM microsoft/dotnet:2.1-sdk AS build
|
||||
WORKDIR /src
|
||||
COPY app/Microsoft.Azure.IIoT.OpcUa.Services.Vault.App.csproj app/
|
||||
COPY api-csharp/Microsoft.Azure.IIoT.OpcUa.Api.Vault.csproj api-csharp/
|
||||
RUN dotnet restore app/Microsoft.Azure.IIoT.OpcUa.Services.Vault.App.csproj
|
||||
COPY app app/
|
||||
COPY api-csharp api-csharp/
|
||||
WORKDIR /src/app
|
||||
RUN dotnet build Microsoft.Azure.IIoT.OpcUa.Services.Vault.App.csproj -c Release -o /app
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish Microsoft.Azure.IIoT.OpcUa.Services.Vault.App.csproj -c Release -o /app
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app .
|
||||
ENTRYPOINT ["dotnet", "Microsoft.Azure.IIoT.OpcUa.Services.Vault.App.dll"]
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
FROM microsoft/dotnet:2.2-runtime AS base
|
||||
WORKDIR /module
|
||||
EXPOSE 58850-58852
|
||||
|
||||
FROM microsoft/dotnet:2.2-sdk AS build
|
||||
WORKDIR /src
|
||||
COPY module/Microsoft.Azure.IIoT.OpcUa.Modules.Vault.csproj module/
|
||||
COPY api-csharp/Microsoft.Azure.IIoT.OpcUa.Api.Vault.csproj api-csharp/
|
||||
RUN dotnet restore module/Microsoft.Azure.IIoT.OpcUa.Modules.Vault.csproj
|
||||
COPY module module/
|
||||
COPY api-csharp api-csharp/
|
||||
WORKDIR /src/module
|
||||
RUN dotnet build Microsoft.Azure.IIoT.OpcUa.Modules.Vault.csproj -c Release -o /module
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish Microsoft.Azure.IIoT.OpcUa.Modules.Vault.csproj -c Release -o /module
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /module
|
||||
COPY --from=publish /module .
|
||||
|
||||
ENTRYPOINT ["dotnet", "Microsoft.Azure.IIoT.OpcUa.Modules.Vault.dll"]
|
12
NuGet.Config
12
NuGet.Config
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="nugetv3" value="https://api.nuget.org/v3/index.json" />
|
||||
<add key="myget" value="https://www.myget.org/F/azureiiot/api/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
<packageSources>
|
||||
<add key="nugetv3" value="https://api.nuget.org/v3/index.json" />
|
||||
<add key="myget" value="https://www.myget.org/F/azureiiot/api/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
## Azure Industrial IoT Services
|
||||
|
||||
[![Build status](https://msazure.visualstudio.com/One/_apis/build/status/Custom/Azure_IOT/Industrial/Components/ci-azure-iiot-opc-vault-service)](https://msazure.visualstudio.com/One/_build/latest?definitionId=44197)
|
||||
|
||||
### OPC Unified Architecture (OPC UA) Certificate Management Service
|
||||
|
||||
The certificate management service for OPC UA facilitates a CA certificate cloud service for OPC UA devices
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 56310
|
||||
EXPOSE 44342
|
||||
|
||||
FROM microsoft/dotnet:2.1-sdk AS build
|
||||
WORKDIR /src
|
||||
COPY Microsoft.Azure.IIoT.OpcUa.Services.Vault.App.csproj Vault.App/
|
||||
RUN dotnet restore Vault.App/Microsoft.Azure.IIoT.OpcUa.Services.Vault.App.csproj
|
||||
COPY . .
|
||||
WORKDIR /src/Vault.App
|
||||
RUN dotnet build Microsoft.Azure.IIoT.OpcUa.Services.Gds.Vault.csproj -c Release -o /app
|
||||
|
||||
FROM build AS publish
|
||||
RUN dotnet publish Microsoft.Azure.IIoT.OpcUa.Services.Gds.Vault.csproj -c Release -o /app
|
||||
|
||||
FROM base AS final
|
||||
WORKDIR /app
|
||||
COPY --from=publish /app .
|
||||
ENTRYPOINT ["dotnet", "Microsoft.Azure.IIoT.OpcUa.Services.Vault.App.dll"]
|
|
@ -5,18 +5,13 @@ VisualStudioVersion = 15.0.27130.2036
|
|||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8289AFAE-0933-40EF-9D19-6FFA2DB04837}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.dockerignore = .dockerignore
|
||||
.editorconfig = .editorconfig
|
||||
.gitattributes = .gitattributes
|
||||
.gitignore = .gitignore
|
||||
.travis.yml = .travis.yml
|
||||
common.props = common.props
|
||||
CONTRIBUTING.md = CONTRIBUTING.md
|
||||
DEVELOPMENT.md = DEVELOPMENT.md
|
||||
src\Dockerfile = src\Dockerfile
|
||||
app\Dockerfile = app\Dockerfile
|
||||
src\Dockerfile.Windows = src\Dockerfile.Windows
|
||||
LICENSE = LICENSE
|
||||
Directory.Build.props = Directory.Build.props
|
||||
license.txt = license.txt
|
||||
NuGet.Config = NuGet.Config
|
||||
project.props = project.props
|
||||
version.props = version.props
|
||||
EndProjectSection
|
||||
|
@ -33,6 +28,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.IIoT.OpcUa.
|
|||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{E9C6A792-1D70-4DE9-B5FB-8D8BCAA223EE}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
CONTRIBUTING.md = CONTRIBUTING.md
|
||||
DEVELOPMENT.md = DEVELOPMENT.md
|
||||
docs\howto-deploy-services.md = docs\howto-deploy-services.md
|
||||
docs\howto-run-services-locally.md = docs\howto-run-services-locally.md
|
||||
README.md = README.md
|
||||
|
@ -45,6 +42,22 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "deploy", "deploy", "{A3FF1E
|
|||
deploy\KeyVault.Secret.Groups.json = deploy\KeyVault.Secret.Groups.json
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cloud", "cloud", "{ECDA661E-A357-4472-B98F-3E0D807965A9}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
deploy\cloud\run.ps1 = deploy\cloud\run.ps1
|
||||
deploy\cloud\template.json = deploy\cloud\template.json
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{1724C572-75C3-4A4C-A710-3D8C3A3223BF}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.dockerignore = .dockerignore
|
||||
Dockerfile = Dockerfile
|
||||
Dockerfile.app = Dockerfile.app
|
||||
Dockerfile.module = Dockerfile.module
|
||||
Dockerfile.Windows = Dockerfile.Windows
|
||||
Dockerfile.Windows-Server2016 = Dockerfile.Windows-Server2016
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -75,6 +88,9 @@ Global
|
|||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{ECDA661E-A357-4472-B98F-3E0D807965A9} = {A3FF1EEF-11DA-470B-9C98-B043B3CB4DE7}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {F947AAE7-2D6B-43C0-B5E6-824B8E4D7992}
|
||||
EndGlobalSection
|
||||
|
|
|
@ -1 +1,14 @@
|
|||
[{"Id":"Default","CertificateType":"RsaSha256ApplicationCertificateType","SubjectName":"CN=Azure Industrial IoT CA, O=Microsoft Corp.","BaseStorePath":"/default","DefaultCertificateLifetime":12,"DefaultCertificateKeySize":2048,"DefaultCertificateHashSize":256,"CACertificateLifetime":60,"CACertificateKeySize":2048,"CACertificateHashSize":256}]
|
||||
[
|
||||
{
|
||||
"Id": "Default",
|
||||
"CertificateType": "RsaSha256ApplicationCertificateType",
|
||||
"SubjectName": "CN=Azure Industrial IoT CA, O=Microsoft Corp.",
|
||||
"BaseStorePath": "/default",
|
||||
"DefaultCertificateLifetime": 12,
|
||||
"DefaultCertificateKeySize": 2048,
|
||||
"DefaultCertificateHashSize": 256,
|
||||
"CACertificateLifetime": 60,
|
||||
"CACertificateKeySize": 2048,
|
||||
"CACertificateHashSize": 256
|
||||
}
|
||||
]
|
||||
|
|
|
@ -703,7 +703,7 @@ Function GetAzureADApplicationConfig() {
|
|||
$requiredResourcesAccess = `
|
||||
New-Object System.Collections.Generic.List[Microsoft.Open.AzureAD.Model.RequiredResourceAccess]
|
||||
$requiredPermissions = GetRequiredPermissions -servicePrincipal $serviceServicePrincipal `
|
||||
-requiredDelegatedPermissions "user_impersonation" # "Directory.Read.All|User.Read"
|
||||
-requiredDelegatedPermissions "user_impersonation"
|
||||
$requiredResourcesAccess.Add($requiredPermissions)
|
||||
$requiredPermissions = GetRequiredPermissions -appId "00000002-0000-0000-c000-000000000000" `
|
||||
-requiredDelegatedPermissions "User.Read"
|
||||
|
@ -721,7 +721,7 @@ Function GetAzureADApplicationConfig() {
|
|||
$requiredResourcesAccess = `
|
||||
New-Object System.Collections.Generic.List[Microsoft.Open.AzureAD.Model.RequiredResourceAccess]
|
||||
$requiredPermissions = GetRequiredPermissions -servicePrincipal $serviceServicePrincipal `
|
||||
-requiredDelegatedPermissions "user_impersonation" # "Directory.Read.All|User.Read"
|
||||
-requiredDelegatedPermissions "user_impersonation"
|
||||
$requiredResourcesAccess.Add($requiredPermissions)
|
||||
$requiredPermissions = GetRequiredPermissions -appId "00000002-0000-0000-c000-000000000000" `
|
||||
-requiredDelegatedPermissions "User.Read"
|
||||
|
@ -936,8 +936,8 @@ Write-Host "--secret="$aadConfig.ModuleSecret
|
|||
Write-Host "--tenantid="$aadConfig.TenantId
|
||||
|
||||
# prepare the GDS module docker image
|
||||
cd ..\module\docker\linux
|
||||
.\dockerbuild.bat
|
||||
cd ..
|
||||
docker build --file .\Dockerfile.module -t edgeopcvault .
|
||||
cd $deploydir
|
||||
|
||||
# create batch file for user to start GDS docker container
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
MIT License
|
||||
|
||||
Azure Industrial IoT Certificate Management Service
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
|
@ -19,3 +22,5 @@
|
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
FROM microsoft/dotnet:2.2-runtime
|
||||
|
||||
COPY ./publish /publish
|
||||
WORKDIR /publish
|
||||
|
||||
ENTRYPOINT ["dotnet", "Microsoft.Azure.IIoT.OpcUa.Modules.Vault.dll"]
|
|
@ -1,4 +0,0 @@
|
|||
dotnet build ..\..\Microsoft.Azure.IIoT.OpcUa.Modules.Vault.csproj
|
||||
dotnet publish ..\..\Microsoft.Azure.IIoT.OpcUa.Modules.Vault.csproj -o ./docker/linux/publish
|
||||
docker build -t edgeopcvault .
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
rem start docker with mapped logs
|
||||
rem push image: docker push mregen/edgeopcvault:latest
|
||||
docker run -it -p 58850-58852:58850-58852 -e 58850-58852 -h %COMPUTERNAME% -v "/c/GDS:/root/.local/share/Microsoft/GDS" edgeopcvault:latest --vault="https://vault012-service.azurewebsites.net" --resource="46f44d87-87a2-4d91-ad34-f0ed5d6031ed" --clientid="f5a38dd7-4282-49eb-b1f3-d50b72462588" --secret="ydZ0rxTzsDrik09c4sFRKmF0jgNO0yAB+93vcdRLCs4=" --tenantid="660722d6-c658-431c-8b2e-a157f3134da5"
|
||||
|
|
@ -27,6 +27,8 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
const int _defaultRecordsPerQuery = 10;
|
||||
private readonly ILogger _log;
|
||||
private readonly string _endpoint;
|
||||
private readonly string _dataBaseId;
|
||||
private readonly string _collectionId;
|
||||
private readonly SecureString _authKeyOrResourceToken;
|
||||
private readonly ILifetimeScope _scope = null;
|
||||
|
||||
|
@ -37,6 +39,8 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
{
|
||||
_scope = scope;
|
||||
_endpoint = config.CosmosDBEndpoint;
|
||||
_dataBaseId = config.CosmosDBDatabase;
|
||||
_collectionId = config.CosmosDBCollection;
|
||||
_authKeyOrResourceToken = new SecureString();
|
||||
foreach (char ch in config.CosmosDBToken)
|
||||
{
|
||||
|
@ -389,8 +393,8 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
#region Private Members
|
||||
private void Initialize()
|
||||
{
|
||||
_db = new DocumentDBRepository(_endpoint, _authKeyOrResourceToken);
|
||||
_applications = new DocumentDBCollection<Application>(_db);
|
||||
_db = new DocumentDBRepository(_endpoint, _dataBaseId, _authKeyOrResourceToken);
|
||||
_applications = new DocumentDBCollection<Application>(_db, _collectionId);
|
||||
}
|
||||
|
||||
private string CreateServerQuery(uint startingRecordId, uint maxRecordsToQuery)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
@ -42,11 +42,16 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
);
|
||||
Task<Opc.Ua.Gds.Server.X509Certificate2KeyPair> NewKeyPairRequestAsync(
|
||||
string id,
|
||||
string requestId,
|
||||
string applicationUri,
|
||||
string subjectName,
|
||||
string[] domainNames,
|
||||
string privateKeyFormat,
|
||||
string privateKeyPassword
|
||||
);
|
||||
|
||||
Task<byte[]> LoadPrivateKeyAsync(string id, string requestId, string privateKeyFormat);
|
||||
Task AcceptPrivateKeyAsync(string id, string requestId);
|
||||
Task DeletePrivateKeyAsync(string id, string requestId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -216,6 +216,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
/// <inheritdoc/>
|
||||
public async Task<Opc.Ua.Gds.Server.X509Certificate2KeyPair> NewKeyPairRequestAsync(
|
||||
string id,
|
||||
string requestId,
|
||||
string applicationUri,
|
||||
string subjectName,
|
||||
string[] domainNames,
|
||||
|
@ -229,7 +230,9 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
ApplicationNames = new Opc.Ua.LocalizedTextCollection(),
|
||||
ApplicationUri = applicationUri
|
||||
};
|
||||
return await certificateGroup.NewKeyPairRequestAsync(app, subjectName, domainNames, privateKeyFormat, privateKeyPassword).ConfigureAwait(false);
|
||||
var keyPair = await certificateGroup.NewKeyPairRequestAsync(app, subjectName, domainNames, privateKeyFormat, privateKeyPassword).ConfigureAwait(false);
|
||||
await certificateGroup.ImportCertKeySecret(id, requestId, keyPair.PrivateKey, keyPair.PrivateKeyFormat);
|
||||
return keyPair;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
@ -252,6 +255,27 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
return crlList;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<byte[]> LoadPrivateKeyAsync(string id, string requestId, string privateKeyFormat)
|
||||
{
|
||||
var certificateGroup = await KeyVaultCertificateGroupProvider.Create(_keyVaultServiceClient, id).ConfigureAwait(false);
|
||||
return await certificateGroup.LoadCertKeySecret(id, requestId, privateKeyFormat);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task AcceptPrivateKeyAsync(string id, string requestId)
|
||||
{
|
||||
var certificateGroup = await KeyVaultCertificateGroupProvider.Create(_keyVaultServiceClient, id).ConfigureAwait(false);
|
||||
await certificateGroup.AcceptCertKeySecret(id, requestId);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task DeletePrivateKeyAsync(string id, string requestId)
|
||||
{
|
||||
var certificateGroup = await KeyVaultCertificateGroupProvider.Create(_keyVaultServiceClient, id).ConfigureAwait(false);
|
||||
await certificateGroup.DeleteCertKeySecret(id, requestId);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<KeyVaultTrustListModel> GetTrustListAsync(string id, int? maxResults = null, string nextPageLink = null)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
@ -32,10 +32,12 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
public readonly ExpandedNodeId DefaultHttpsGroupId;
|
||||
public readonly ExpandedNodeId DefaultUserTokenGroupId;
|
||||
|
||||
private readonly ILogger _log;
|
||||
internal IApplicationsDatabase ApplicationsDatabase;
|
||||
internal ICertificateGroup CertificateGroup;
|
||||
internal IApplicationsDatabase _applicationsDatabase;
|
||||
internal ICertificateGroup _certificateGroup;
|
||||
private readonly string _endpoint;
|
||||
private readonly string _dataBaseId;
|
||||
private readonly string _collectionId;
|
||||
private readonly ILogger _log;
|
||||
private SecureString _authKeyOrResourceToken;
|
||||
|
||||
public CosmosDBCertificateRequest(
|
||||
|
@ -44,9 +46,11 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
IServicesConfig config,
|
||||
ILogger logger)
|
||||
{
|
||||
ApplicationsDatabase = database;
|
||||
CertificateGroup = certificateGroup;
|
||||
_applicationsDatabase = database;
|
||||
_certificateGroup = certificateGroup;
|
||||
_dataBaseId = config.CosmosDBDatabase;
|
||||
_endpoint = config.CosmosDBEndpoint;
|
||||
_collectionId = config.CosmosDBCollection;
|
||||
_authKeyOrResourceToken = new SecureString();
|
||||
foreach (char ch in config.CosmosDBToken)
|
||||
{
|
||||
|
@ -66,8 +70,8 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
#region ICertificateRequest
|
||||
public Task Initialize()
|
||||
{
|
||||
var db = new DocumentDBRepository(_endpoint, _authKeyOrResourceToken);
|
||||
CertificateRequests = new DocumentDBCollection<CosmosDB.Models.CertificateRequest>(db);
|
||||
var db = new DocumentDBRepository(_endpoint, _dataBaseId, _authKeyOrResourceToken);
|
||||
_certificateRequests = new DocumentDBCollection<CosmosDB.Models.CertificateRequest>(db, _collectionId);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
@ -75,9 +79,9 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
{
|
||||
try
|
||||
{
|
||||
var onBehalfOfCertificateGroup = await CertificateGroup.OnBehalfOfRequest(request);
|
||||
var onBehalfOfCertificateGroup = await _certificateGroup.OnBehalfOfRequest(request);
|
||||
var certRequest = (CosmosDBCertificateRequest)this.MemberwiseClone();
|
||||
certRequest.CertificateGroup = onBehalfOfCertificateGroup;
|
||||
certRequest._certificateGroup = onBehalfOfCertificateGroup;
|
||||
return certRequest;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -95,7 +99,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
byte[] certificateSigningRequest,
|
||||
string authorityId)
|
||||
{
|
||||
Application application = await ApplicationsDatabase.GetApplicationAsync(applicationId);
|
||||
Application application = await _applicationsDatabase.GetApplicationAsync(applicationId);
|
||||
if (application == null)
|
||||
{
|
||||
throw new ServiceResultException(StatusCodes.BadNotFound, "The ApplicationId does not refer to a valid application.");
|
||||
|
@ -133,7 +137,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
|
||||
if (isNew)
|
||||
{
|
||||
await CertificateRequests.CreateAsync(request);
|
||||
await _certificateRequests.CreateAsync(request);
|
||||
}
|
||||
|
||||
return request.RequestId.ToString();
|
||||
|
@ -149,7 +153,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
string privateKeyPassword,
|
||||
string authorityId)
|
||||
{
|
||||
Application application = await ApplicationsDatabase.GetApplicationAsync(applicationId);
|
||||
Application application = await _applicationsDatabase.GetApplicationAsync(applicationId);
|
||||
if (application == null)
|
||||
{
|
||||
throw new ServiceResultException(StatusCodes.BadNodeIdUnknown);
|
||||
|
@ -239,7 +243,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
|
||||
if (isNew)
|
||||
{
|
||||
await CertificateRequests.CreateAsync(request);
|
||||
await _certificateRequests.CreateAsync(request);
|
||||
}
|
||||
|
||||
return request.RequestId.ToString();
|
||||
|
@ -256,7 +260,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
do
|
||||
{
|
||||
retryUpdate = false;
|
||||
CertificateRequest request = await CertificateRequests.GetAsync(reqId);
|
||||
CertificateRequest request = await _certificateRequests.GetAsync(reqId);
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
|
@ -268,7 +272,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
throw new ServiceResultException(StatusCodes.BadInvalidState);
|
||||
}
|
||||
|
||||
Application application = await ApplicationsDatabase.GetApplicationAsync(request.ApplicationId);
|
||||
Application application = await _applicationsDatabase.GetApplicationAsync(request.ApplicationId);
|
||||
if (application == null)
|
||||
{
|
||||
throw new ServiceResultException(StatusCodes.BadNodeIdUnknown, "Unknown application id");
|
||||
|
@ -291,14 +295,13 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
{
|
||||
try
|
||||
{
|
||||
certificate = await CertificateGroup.SigningRequestAsync(
|
||||
certificate = await _certificateGroup.SigningRequestAsync(
|
||||
request.CertificateGroupId,
|
||||
application.ApplicationUri,
|
||||
request.SigningRequest
|
||||
);
|
||||
|
||||
request.Certificate = certificate.RawData;
|
||||
request.PrivateKey = null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -317,8 +320,9 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
X509Certificate2KeyPair newKeyPair = null;
|
||||
try
|
||||
{
|
||||
newKeyPair = await CertificateGroup.NewKeyPairRequestAsync(
|
||||
newKeyPair = await _certificateGroup.NewKeyPairRequestAsync(
|
||||
request.CertificateGroupId,
|
||||
requestId,
|
||||
application.ApplicationUri,
|
||||
request.SubjectName,
|
||||
request.DomainNames,
|
||||
|
@ -337,15 +341,14 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
}
|
||||
|
||||
request.Certificate = newKeyPair.Certificate.RawData;
|
||||
request.PrivateKey = newKeyPair.PrivateKey;
|
||||
|
||||
// ignore private key, it is stored in KeyVault
|
||||
}
|
||||
}
|
||||
|
||||
request.ApproveRejectTime = DateTime.UtcNow;
|
||||
try
|
||||
{
|
||||
await CertificateRequests.UpdateAsync(reqId, request, request.ETag);
|
||||
await _certificateRequests.UpdateAsync(reqId, request, request.ETag);
|
||||
}
|
||||
catch (DocumentClientException dce)
|
||||
{
|
||||
|
@ -362,13 +365,12 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
string requestId)
|
||||
{
|
||||
Guid reqId = GetIdFromString(requestId);
|
||||
|
||||
bool retryUpdate;
|
||||
do
|
||||
{
|
||||
retryUpdate = false;
|
||||
|
||||
CertificateRequest request = await CertificateRequests.GetAsync(reqId);
|
||||
CertificateRequest request = await _certificateRequests.GetAsync(reqId);
|
||||
if (request == null)
|
||||
{
|
||||
throw new ServiceResultException(StatusCodes.BadNodeIdUnknown);
|
||||
|
@ -379,6 +381,8 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
throw new ServiceResultException(StatusCodes.BadInvalidState);
|
||||
}
|
||||
|
||||
await _certificateGroup.AcceptPrivateKeyAsync(request.CertificateGroupId, requestId);
|
||||
|
||||
request.State = CertificateRequestState.Accepted;
|
||||
|
||||
// erase information which is not required anymore
|
||||
|
@ -388,7 +392,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
request.AcceptTime = DateTime.UtcNow;
|
||||
try
|
||||
{
|
||||
await CertificateRequests.UpdateAsync(request.RequestId, request, request.ETag);
|
||||
await _certificateRequests.UpdateAsync(request.RequestId, request, request.ETag);
|
||||
}
|
||||
catch (DocumentClientException dce)
|
||||
{
|
||||
|
@ -398,6 +402,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
}
|
||||
}
|
||||
} while (retryUpdate);
|
||||
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(string requestId)
|
||||
|
@ -409,7 +414,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
{
|
||||
retryUpdate = false;
|
||||
|
||||
CertificateRequest request = await CertificateRequests.GetAsync(reqId);
|
||||
CertificateRequest request = await _certificateRequests.GetAsync(reqId);
|
||||
if (request == null)
|
||||
{
|
||||
throw new ServiceResultException(StatusCodes.BadNodeIdUnknown);
|
||||
|
@ -417,6 +422,8 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
|
||||
request.State = CertificateRequestState.Deleted;
|
||||
|
||||
await _certificateGroup.DeletePrivateKeyAsync(request.CertificateGroupId, requestId);
|
||||
|
||||
// erase information which is not required anymore
|
||||
request.SigningRequest = null;
|
||||
request.PrivateKeyFormat = null;
|
||||
|
@ -424,7 +431,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
request.DeleteTime = DateTime.UtcNow;
|
||||
try
|
||||
{
|
||||
await CertificateRequests.UpdateAsync(request.RequestId, request, request.ETag);
|
||||
await _certificateRequests.UpdateAsync(request.RequestId, request, request.ETag);
|
||||
}
|
||||
catch (DocumentClientException dce)
|
||||
{
|
||||
|
@ -434,6 +441,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
}
|
||||
}
|
||||
} while (retryUpdate);
|
||||
|
||||
}
|
||||
|
||||
public async Task RevokeAsync(string requestId)
|
||||
|
@ -444,7 +452,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
do
|
||||
{
|
||||
retryUpdate = false;
|
||||
CertificateRequest request = await CertificateRequests.GetAsync(reqId);
|
||||
CertificateRequest request = await _certificateRequests.GetAsync(reqId);
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
|
@ -466,12 +474,11 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
request.PrivateKeyFormat = null;
|
||||
request.SigningRequest = null;
|
||||
request.PrivateKeyPassword = null;
|
||||
request.PrivateKey = null;
|
||||
|
||||
try
|
||||
{
|
||||
var cert = new X509Certificate2(request.Certificate);
|
||||
var crl = await CertificateGroup.RevokeCertificateAsync(request.CertificateGroupId, cert);
|
||||
var crl = await _certificateGroup.RevokeCertificateAsync(request.CertificateGroupId, cert);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -486,7 +493,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
|
||||
try
|
||||
{
|
||||
await CertificateRequests.UpdateAsync(reqId, request, request.ETag);
|
||||
await _certificateRequests.UpdateAsync(reqId, request, request.ETag);
|
||||
}
|
||||
catch (DocumentClientException dce)
|
||||
{
|
||||
|
@ -502,7 +509,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
{
|
||||
Guid reqId = GetIdFromString(requestId);
|
||||
|
||||
CertificateRequest request = await CertificateRequests.GetAsync(reqId);
|
||||
CertificateRequest request = await _certificateRequests.GetAsync(reqId);
|
||||
if (request == null)
|
||||
{
|
||||
throw new ServiceResultException(StatusCodes.BadNodeIdUnknown);
|
||||
|
@ -514,13 +521,13 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
throw new ServiceResultException(StatusCodes.BadInvalidState);
|
||||
}
|
||||
|
||||
await CertificateRequests.DeleteAsync(request.RequestId);
|
||||
await _certificateRequests.DeleteAsync(request.RequestId);
|
||||
}
|
||||
|
||||
public async Task RevokeGroupAsync(string groupId, bool? allVersions)
|
||||
{
|
||||
// TODO: implement all versions to renew all CSR for all CA versions
|
||||
var deletedRequests = await CertificateRequests.GetAsync(x => x.State == CertificateRequestState.Deleted);
|
||||
var deletedRequests = await _certificateRequests.GetAsync(x => x.State == CertificateRequestState.Deleted);
|
||||
if (deletedRequests == null ||
|
||||
deletedRequests.Count() == 0)
|
||||
{
|
||||
|
@ -543,11 +550,11 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
{
|
||||
// skip
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
await CertificateGroup.RevokeCertificatesAsync(groupId, certCollection);
|
||||
await _certificateGroup.RevokeCertificatesAsync(groupId, certCollection);
|
||||
|
||||
foreach (var reqId in deletedRequests)
|
||||
{
|
||||
|
@ -555,7 +562,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
do
|
||||
{
|
||||
retryUpdate = false;
|
||||
CertificateRequest request = await CertificateRequests.GetAsync(reqId.RequestId);
|
||||
CertificateRequest request = await _certificateRequests.GetAsync(reqId.RequestId);
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
|
@ -579,11 +586,10 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
request.PrivateKeyFormat = null;
|
||||
request.SigningRequest = null;
|
||||
request.PrivateKeyPassword = null;
|
||||
request.PrivateKey = null;
|
||||
|
||||
try
|
||||
{
|
||||
await CertificateRequests.UpdateAsync(reqId.RequestId, request, request.ETag);
|
||||
await _certificateRequests.UpdateAsync(reqId.RequestId, request, request.ETag);
|
||||
}
|
||||
catch (DocumentClientException dce)
|
||||
{
|
||||
|
@ -603,13 +609,13 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
{
|
||||
Guid reqId = GetIdFromString(requestId);
|
||||
|
||||
Application application = await ApplicationsDatabase.GetApplicationAsync(applicationId);
|
||||
Application application = await _applicationsDatabase.GetApplicationAsync(applicationId);
|
||||
if (application == null)
|
||||
{
|
||||
throw new ServiceResultException(StatusCodes.BadNodeIdUnknown);
|
||||
}
|
||||
|
||||
CertificateRequest request = await CertificateRequests.GetAsync(reqId);
|
||||
CertificateRequest request = await _certificateRequests.GetAsync(reqId);
|
||||
if (request == null)
|
||||
{
|
||||
throw new ServiceResultException(StatusCodes.BadNodeIdUnknown);
|
||||
|
@ -632,6 +638,9 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
throw new ServiceResultException(StatusCodes.BadNodeIdUnknown);
|
||||
}
|
||||
|
||||
// get private key
|
||||
byte[] privateKey = await _certificateGroup.LoadPrivateKeyAsync(request.CertificateGroupId, requestId, request.PrivateKeyFormat);
|
||||
|
||||
return new FinishRequestResultModel(
|
||||
request.State,
|
||||
applicationId,
|
||||
|
@ -640,7 +649,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
request.CertificateTypeId,
|
||||
request.Certificate,
|
||||
request.PrivateKeyFormat,
|
||||
request.PrivateKey,
|
||||
privateKey,
|
||||
request.AuthorityId);
|
||||
}
|
||||
|
||||
|
@ -650,7 +659,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
{
|
||||
Guid reqId = GetIdFromString(requestId);
|
||||
|
||||
CertificateRequest request = await CertificateRequests.GetAsync(reqId);
|
||||
CertificateRequest request = await _certificateRequests.GetAsync(reqId);
|
||||
if (request == null)
|
||||
{
|
||||
throw new ServiceResultException(StatusCodes.BadNodeIdUnknown);
|
||||
|
@ -682,7 +691,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
|
||||
}
|
||||
|
||||
public async Task<(string,ReadRequestResultModel[])> QueryPageAsync(
|
||||
public async Task<(string, ReadRequestResultModel[])> QueryPageAsync(
|
||||
string appId,
|
||||
CertificateRequestState? state,
|
||||
string nextPageLink,
|
||||
|
@ -691,19 +700,19 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
IEnumerable<CertificateRequest> requests;
|
||||
if (appId == null && state == null)
|
||||
{
|
||||
(nextPageLink, requests) = await CertificateRequests.GetPageAsync(x => x.State < CertificateRequestState.Deleted, nextPageLink, maxResults);
|
||||
(nextPageLink, requests) = await _certificateRequests.GetPageAsync(x => x.State < CertificateRequestState.Deleted, nextPageLink, maxResults);
|
||||
}
|
||||
else if (appId != null && state != null)
|
||||
{
|
||||
(nextPageLink, requests) = await CertificateRequests.GetPageAsync(x => x.ApplicationId == appId && x.State == state, nextPageLink, maxResults);
|
||||
(nextPageLink, requests) = await _certificateRequests.GetPageAsync(x => x.ApplicationId == appId && x.State == state, nextPageLink, maxResults);
|
||||
}
|
||||
else if (appId != null)
|
||||
{
|
||||
(nextPageLink, requests) = await CertificateRequests.GetPageAsync(x => x.ApplicationId == appId, nextPageLink, maxResults);
|
||||
(nextPageLink, requests) = await _certificateRequests.GetPageAsync(x => x.ApplicationId == appId, nextPageLink, maxResults);
|
||||
}
|
||||
else
|
||||
{
|
||||
(nextPageLink, requests) = await CertificateRequests.GetPageAsync(x => x.State == state, nextPageLink, maxResults);
|
||||
(nextPageLink, requests) = await _certificateRequests.GetPageAsync(x => x.State == state, nextPageLink, maxResults);
|
||||
}
|
||||
List<ReadRequestResultModel> result = new List<ReadRequestResultModel>();
|
||||
foreach (CertificateRequest request in requests)
|
||||
|
@ -871,8 +880,8 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault
|
|||
#endregion
|
||||
|
||||
#region Private Fields
|
||||
private DateTime queryCounterResetTime = DateTime.UtcNow;
|
||||
private IDocumentDBCollection<CertificateRequest> CertificateRequests;
|
||||
private DateTime _queryCounterResetTime = DateTime.UtcNow;
|
||||
private IDocumentDBCollection<CertificateRequest> _certificateRequests;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
@ -33,9 +33,13 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.CosmosDB
|
|||
public DocumentDBCollection(IDocumentDBRepository db, string collectionId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(collectionId))
|
||||
{
|
||||
throw new ArgumentNullException("collectionId must be set");
|
||||
}
|
||||
if (db == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(db));
|
||||
}
|
||||
|
||||
this.CollectionId = collectionId;
|
||||
this.db = db;
|
||||
|
@ -217,4 +221,4 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.CosmosDB
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
@ -15,16 +15,18 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.CosmosDB
|
|||
public class DocumentDBRepository : IDocumentDBRepository
|
||||
{
|
||||
public DocumentClient Client { get; }
|
||||
public string DatabaseId { get { return "OpcVault"; } }
|
||||
public string DatabaseId { get; }
|
||||
|
||||
public DocumentDBRepository(string endpoint, string authKeyOrResourceToken)
|
||||
public DocumentDBRepository(string endpoint, string dataBaseId, string authKeyOrResourceToken)
|
||||
{
|
||||
this.DatabaseId = dataBaseId;
|
||||
this.Client = new DocumentClient(new Uri(endpoint), authKeyOrResourceToken);
|
||||
CreateDatabaseIfNotExistsAsync().Wait();
|
||||
}
|
||||
|
||||
public DocumentDBRepository(string endpoint, SecureString authKeyOrResourceToken)
|
||||
public DocumentDBRepository(string endpoint, string dataBaseId, SecureString authKeyOrResourceToken)
|
||||
{
|
||||
this.DatabaseId = dataBaseId;
|
||||
this.Client = new DocumentClient(new Uri(endpoint), authKeyOrResourceToken);
|
||||
CreateDatabaseIfNotExistsAsync().Wait();
|
||||
}
|
||||
|
@ -48,4 +50,4 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.CosmosDB
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
@ -12,4 +12,4 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.CosmosDB
|
|||
DocumentClient Client { get; }
|
||||
string DatabaseId { get; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
@ -33,7 +33,6 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.CosmosDB.Models
|
|||
public string SubjectName { get; set; }
|
||||
public string[] DomainNames { get; set; }
|
||||
public string PrivateKeyFormat { get; set; }
|
||||
public byte[] PrivateKey { get; set; }
|
||||
public string PrivateKeyPassword { get; set; }
|
||||
public string AuthorityId { get; set; }
|
||||
public byte[] Certificate { get; set; }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
@ -14,7 +14,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Diagnostics
|
|||
public class Serialization
|
||||
{
|
||||
// Save memory avoiding serializations that go too deep
|
||||
private static readonly JsonSerializerSettings serializationSettings =
|
||||
private static readonly JsonSerializerSettings _serializationSettings =
|
||||
new JsonSerializerSettings
|
||||
{
|
||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
|
||||
|
@ -44,7 +44,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Diagnostics
|
|||
}
|
||||
}
|
||||
|
||||
return JsonConvert.SerializeObject(logdata, serializationSettings);
|
||||
return JsonConvert.SerializeObject(logdata, _serializationSettings);
|
||||
}
|
||||
|
||||
private static object SerializeException(Exception e, int depth = 3)
|
||||
|
@ -52,8 +52,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Diagnostics
|
|||
if (e == null) return null;
|
||||
if (depth == 0) return "-max serialization depth reached-";
|
||||
|
||||
var exception = e as AggregateException;
|
||||
if (exception != null)
|
||||
if (e is AggregateException exception)
|
||||
{
|
||||
var innerExceptions = exception.InnerExceptions
|
||||
.Select(ie => SerializeException(ie, depth - 1)).ToList();
|
||||
|
|
|
@ -21,7 +21,6 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
{
|
||||
public sealed class KeyVaultCertificateGroupProvider : Opc.Ua.Gds.Server.CertificateGroup
|
||||
{
|
||||
public TimeSpan CrlUpdateTime = TimeSpan.FromDays(30);
|
||||
public X509CRL Crl;
|
||||
public X509SignatureGenerator x509SignatureGenerator;
|
||||
|
||||
|
@ -140,7 +139,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
#region ICertificateGroupProvider
|
||||
public override async Task Init()
|
||||
{
|
||||
await semaphoreSlim.WaitAsync();
|
||||
await _semaphoreSlim.WaitAsync();
|
||||
try
|
||||
{
|
||||
Opc.Ua.Utils.Trace(Opc.Ua.Utils.TraceMasks.Information, "InitializeCertificateGroup: {0}", m_subjectName);
|
||||
|
@ -167,7 +166,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
}
|
||||
finally
|
||||
{
|
||||
semaphoreSlim.Release();
|
||||
_semaphoreSlim.Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,7 +176,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
/// </summary>
|
||||
public async Task<bool> CreateImportedCACertificateAsync()
|
||||
{
|
||||
await semaphoreSlim.WaitAsync();
|
||||
await _semaphoreSlim.WaitAsync();
|
||||
try
|
||||
{
|
||||
|
||||
|
@ -217,7 +216,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
}
|
||||
finally
|
||||
{
|
||||
semaphoreSlim.Release();
|
||||
_semaphoreSlim.Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,7 +225,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
/// </summary>
|
||||
public async Task<bool> CreateCACertificateAsync()
|
||||
{
|
||||
await semaphoreSlim.WaitAsync();
|
||||
await _semaphoreSlim.WaitAsync();
|
||||
try
|
||||
{
|
||||
DateTime notBefore = TrimmedNotBeforeDate();
|
||||
|
@ -254,7 +253,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
|
||||
// create default revocation list, sign with KeyVault
|
||||
Crl = RevokeCertificate(Certificate, null, null,
|
||||
notBefore, notBefore + CrlUpdateTime,
|
||||
notBefore, DateTime.MinValue,
|
||||
new KeyVaultSignatureGenerator(_keyVaultServiceClient, _caCertKeyIdentifier, Certificate),
|
||||
this.Configuration.CACertificateHashSize);
|
||||
|
||||
|
@ -265,7 +264,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
}
|
||||
finally
|
||||
{
|
||||
semaphoreSlim.Release();
|
||||
_semaphoreSlim.Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,7 +290,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
var crl = await _keyVaultServiceClient.LoadCACrl(Configuration.Id, caCertKeyInfo.Certificate);
|
||||
var crls = new List<X509CRL>() { crl };
|
||||
var newCrl = RevokeCertificate(caCertKeyInfo.Certificate, crls, certificates,
|
||||
now, now + CrlUpdateTime,
|
||||
now, DateTime.MinValue,
|
||||
new KeyVaultSignatureGenerator(_keyVaultServiceClient, caCertKeyInfo.KeyIdentifier, caCertKeyInfo.Certificate),
|
||||
this.Configuration.CACertificateHashSize);
|
||||
await _keyVaultServiceClient.ImportCACrl(Configuration.Id, caCertKeyInfo.Certificate, newCrl).ConfigureAwait(false);
|
||||
|
@ -341,7 +340,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
var crl = await _keyVaultServiceClient.LoadCACrl(Configuration.Id, caCertKeyInfo.Certificate);
|
||||
var crls = new List<X509CRL>() { crl };
|
||||
var newCrl = RevokeCertificate(caCertKeyInfo.Certificate, crls, caRevokeCollection,
|
||||
now, now + CrlUpdateTime,
|
||||
now, DateTime.MinValue,
|
||||
new KeyVaultSignatureGenerator(_keyVaultServiceClient, caCertKeyInfo.KeyIdentifier, caCertKeyInfo.Certificate),
|
||||
this.Configuration.CACertificateHashSize);
|
||||
await _keyVaultServiceClient.ImportCACrl(Configuration.Id, caCertKeyInfo.Certificate, newCrl).ConfigureAwait(false);
|
||||
|
@ -356,9 +355,9 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new key pair with certificate offline and signs it with KeyVault.
|
||||
/// Creates a new key pair with KeyVault and signs it with KeyVault.
|
||||
/// </summary>
|
||||
public override async Task<X509Certificate2KeyPair> NewKeyPairRequestAsync(
|
||||
public async Task<X509Certificate2KeyPair> NewKeyPairRequestKeyVaultAsync(
|
||||
ApplicationRecordDataType application,
|
||||
string subjectName,
|
||||
string[] domainNames,
|
||||
|
@ -369,7 +368,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
|
||||
DateTime notBefore = TrimmedNotBeforeDate();
|
||||
DateTime notAfter = notBefore.AddMonths(Configuration.DefaultCertificateLifetime);
|
||||
// create new cert in HSM storage
|
||||
// create new cert with KeyVault
|
||||
using (var signedCertWithPrivateKey = await _keyVaultServiceClient.CreateSignedKeyPairAsync(
|
||||
Configuration.Id,
|
||||
Certificate,
|
||||
|
@ -404,7 +403,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
/// <summary>
|
||||
/// Creates a new key pair with certificate offline and signs it with KeyVault.
|
||||
/// </summary>
|
||||
public async Task<X509Certificate2KeyPair> NewKeyPairRequestOfflineAsync(
|
||||
public override async Task<X509Certificate2KeyPair> NewKeyPairRequestAsync(
|
||||
ApplicationRecordDataType application,
|
||||
string subjectName,
|
||||
string[] domainNames,
|
||||
|
@ -458,11 +457,44 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
{
|
||||
throw new ServiceResultException(StatusCodes.BadInvalidArgument, "Invalid private key format");
|
||||
}
|
||||
|
||||
return new X509Certificate2KeyPair(new X509Certificate2(signedCertWithPrivateKey.RawData), privateKeyFormat, privateKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores the private key of a cert request in a Key Vault secret.
|
||||
/// </summary>
|
||||
public async Task ImportCertKeySecret(string id, string requestId, byte[] privateKey, string privateKeyFormat, CancellationToken ct = default)
|
||||
{
|
||||
await _keyVaultServiceClient.ImportCertKey(id, requestId, privateKey, privateKeyFormat, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the private key of a cert request from Key Vault secret.
|
||||
/// </summary>
|
||||
public async Task<byte[]> LoadCertKeySecret(string id, string requestId, string privateKeyFormat, CancellationToken ct = default)
|
||||
{
|
||||
return await _keyVaultServiceClient.LoadCertKey(id, requestId, privateKeyFormat, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accept the private key of a cert request from Key Vault secret.
|
||||
/// </summary>
|
||||
public async Task AcceptCertKeySecret(string id, string requestId, CancellationToken ct = default)
|
||||
{
|
||||
await _keyVaultServiceClient.AcceptCertKey(id, requestId, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete the private key of a cert request from Key Vault secret.
|
||||
/// </summary>
|
||||
public async Task DeleteCertKeySecret(string id, string requestId, CancellationToken ct = default)
|
||||
{
|
||||
await _keyVaultServiceClient.DeleteCertKey(id, requestId, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a KeyVault signed certficate from signing request.
|
||||
/// </summary>
|
||||
|
@ -661,13 +693,15 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
|
||||
private static Dictionary<NodeId, string> CertTypeMap()
|
||||
{
|
||||
var certTypeMap = new Dictionary<NodeId, string>();
|
||||
// FUTURE: support more cert types
|
||||
//CertTypeMap.Add(Opc.Ua.ObjectTypeIds.HttpsCertificateType, "HttpsCertificateType");
|
||||
//CertTypeMap.Add(Opc.Ua.ObjectTypeIds.UserCredentialCertificateType, "UserCredentialCertificateType");
|
||||
certTypeMap.Add(Opc.Ua.ObjectTypeIds.ApplicationCertificateType, "ApplicationCertificateType");
|
||||
//CertTypeMap.Add(Opc.Ua.ObjectTypeIds.RsaMinApplicationCertificateType, "RsaMinApplicationCertificateType");
|
||||
certTypeMap.Add(Opc.Ua.ObjectTypeIds.RsaSha256ApplicationCertificateType, "RsaSha256ApplicationCertificateType");
|
||||
var certTypeMap = new Dictionary<NodeId, string>
|
||||
{
|
||||
// FUTURE: support more cert types
|
||||
//{ Opc.Ua.ObjectTypeIds.HttpsCertificateType, "HttpsCertificateType" },
|
||||
//{ Opc.Ua.ObjectTypeIds.UserCredentialCertificateType, "UserCredentialCertificateType" },
|
||||
{ Opc.Ua.ObjectTypeIds.ApplicationCertificateType, "ApplicationCertificateType" },
|
||||
//{ Opc.Ua.ObjectTypeIds.RsaMinApplicationCertificateType, "RsaMinApplicationCertificateType" },
|
||||
{ Opc.Ua.ObjectTypeIds.RsaSha256ApplicationCertificateType, "RsaSha256ApplicationCertificateType" }
|
||||
};
|
||||
return certTypeMap;
|
||||
}
|
||||
|
||||
|
@ -712,6 +746,6 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
private string _caCertSecretIdentifier;
|
||||
private string _caCertKeyIdentifier;
|
||||
private DateTime _lastUpdate;
|
||||
private SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1);
|
||||
private SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(1, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -360,6 +360,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
int keySize,
|
||||
int hashSize,
|
||||
bool trusted,
|
||||
string crlDistributionPoint = null,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
try
|
||||
|
@ -443,7 +444,8 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
null,
|
||||
publicKey,
|
||||
new KeyVaultSignatureGenerator(this, caCertKeyIdentifier, null),
|
||||
true);
|
||||
true,
|
||||
crlDistributionPoint);
|
||||
|
||||
// merge Root CA cert with
|
||||
var mergeResult = await _keyVaultClient.MergeCertificateAsync(
|
||||
|
@ -461,7 +463,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
|
||||
return signedcert;
|
||||
}
|
||||
catch
|
||||
catch
|
||||
{
|
||||
throw new ServiceResultException(StatusCodes.BadInternalError, "Failed to create new Root CA certificate");
|
||||
}
|
||||
|
@ -530,8 +532,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
(ushort)hashSize,
|
||||
issuerCert,
|
||||
publicKey,
|
||||
generator,
|
||||
true);
|
||||
generator);
|
||||
|
||||
// merge signed cert with keystore
|
||||
var mergeResult = await _keyVaultClient.MergeCertificateAsync(
|
||||
|
@ -622,6 +623,75 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Imports a Private Key for group id and certificate.
|
||||
/// </summary>
|
||||
public async Task ImportCertKey(string id, string requestId, byte[] privateKey, string privateKeyFormat, CancellationToken ct = default(CancellationToken))
|
||||
{
|
||||
var contentType = PrivateKeyFormatToContentType(privateKeyFormat);
|
||||
string secretIdentifier = KeySecretName(id, requestId);
|
||||
DateTime now = DateTime.UtcNow;
|
||||
SecretAttributes secretAttributes = new SecretAttributes()
|
||||
{
|
||||
Enabled = true,
|
||||
NotBefore = now - TimeSpan.FromDays(-1),
|
||||
Expires = now + TimeSpan.FromDays(30),
|
||||
};
|
||||
var result = await _keyVaultClient.SetSecretAsync(
|
||||
_vaultBaseUrl,
|
||||
secretIdentifier,
|
||||
(contentType == ContentTypePfx) ? Convert.ToBase64String(privateKey) : Encoding.ASCII.GetString(privateKey),
|
||||
null,
|
||||
contentType,
|
||||
secretAttributes,
|
||||
ct)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load Private Key for certificate in group.
|
||||
/// </summary>
|
||||
public async Task<byte[]> LoadCertKey(string id, string requestId, string privateKeyFormat, CancellationToken ct = default(CancellationToken))
|
||||
{
|
||||
var contentType = PrivateKeyFormatToContentType(privateKeyFormat);
|
||||
string secretIdentifier = KeySecretName(id, requestId);
|
||||
var secret = await _keyVaultClient.GetSecretAsync(_vaultBaseUrl, secretIdentifier, ct).ConfigureAwait(false);
|
||||
if (secret.ContentType == contentType)
|
||||
{
|
||||
if (secret.ContentType == ContentTypePfx)
|
||||
{
|
||||
return Convert.FromBase64String(secret.Value);
|
||||
}
|
||||
else if (secret.ContentType == ContentTypePem)
|
||||
{
|
||||
return Encoding.ASCII.GetBytes(secret.Value);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accept Private Key for certificate in group.
|
||||
/// </summary>
|
||||
public async Task AcceptCertKey(string id, string requestId, CancellationToken ct = default)
|
||||
{
|
||||
string secretIdentifier = KeySecretName(id, requestId);
|
||||
var secretAttributes = new SecretAttributes
|
||||
{
|
||||
Enabled = false
|
||||
};
|
||||
await _keyVaultClient.UpdateSecretAsync(_vaultBaseUrl, secretIdentifier, secretAttributes, null, ct).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete Private Key for certificate in group.
|
||||
/// </summary>
|
||||
public async Task DeleteCertKey(string id, string requestId, CancellationToken ct = default)
|
||||
{
|
||||
string secretIdentifier = KeySecretName(id, requestId);
|
||||
await _keyVaultClient.DeleteSecretAsync(_vaultBaseUrl, secretIdentifier, ct).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a trust list with all certs and crls in issuer and trusted list.
|
||||
/// i) First load all certs and crls tagged with id==Issuer or id==Trusted.
|
||||
|
@ -762,7 +832,9 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
var secretItems = await _keyVaultClient.GetSecretsAsync(_vaultBaseUrl, MaxResults, ct).ConfigureAwait(false);
|
||||
while (secretItems != null)
|
||||
{
|
||||
foreach (var secretItem in secretItems.Where(s => s.ContentType == ContentTypeCrl))
|
||||
foreach (var secretItem in secretItems.Where(s =>
|
||||
(s.ContentType == ContentTypeCrl || s.ContentType == ContentTypePem || s.ContentType == ContentTypePfx)
|
||||
))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -891,7 +963,11 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
|
||||
private string KeyStoreName(string id, string requestId)
|
||||
{
|
||||
return id + "Keys" + requestId;
|
||||
return id + "Key" + requestId;
|
||||
}
|
||||
private string KeySecretName(string id, string requestId)
|
||||
{
|
||||
return id + "Key" + requestId;
|
||||
}
|
||||
private string CrlSecretName(string id, X509Certificate2 certificate)
|
||||
{
|
||||
|
@ -920,6 +996,19 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
return null;
|
||||
}
|
||||
|
||||
private string PrivateKeyFormatToContentType(string privateKeyFormat)
|
||||
{
|
||||
if (privateKeyFormat.Equals("PFX", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return ContentTypePfx;
|
||||
}
|
||||
else if (privateKeyFormat.Equals("PEM", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return ContentTypePem;
|
||||
}
|
||||
throw new Exception("Unknown Private Key format.");
|
||||
}
|
||||
|
||||
private string _vaultBaseUrl;
|
||||
private bool _keyStoreHSM;
|
||||
private IKeyVaultClient _keyVaultClient;
|
||||
|
|
|
@ -38,7 +38,8 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
X509Certificate2 issuerCAKeyCert,
|
||||
RSA publicKey,
|
||||
X509SignatureGenerator generator,
|
||||
bool caCert = false
|
||||
bool caCert = false,
|
||||
string crlDistributionPoint = null
|
||||
)
|
||||
{
|
||||
if (publicKey == null)
|
||||
|
@ -68,7 +69,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
|
||||
// Basic constraints
|
||||
request.CertificateExtensions.Add(
|
||||
new X509BasicConstraintsExtension(caCert, false, 0, true));
|
||||
new X509BasicConstraintsExtension(caCert, caCert, 0, true));
|
||||
|
||||
// Subject Key Identifier
|
||||
var ski = new X509SubjectKeyIdentifierExtension(
|
||||
|
@ -93,6 +94,15 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
new X509KeyUsageExtension(
|
||||
X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyCertSign | X509KeyUsageFlags.CrlSign,
|
||||
true));
|
||||
|
||||
if (crlDistributionPoint != null)
|
||||
{
|
||||
string serial = BitConverter.ToString(serialNumber).Replace("-","").ToLower();
|
||||
// add CRL endpoint, if available
|
||||
request.CertificateExtensions.Add(
|
||||
BuildX509CRLDistributionPoints(crlDistributionPoint.Replace("%serial%", serial))
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -507,6 +517,33 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.KeyVault
|
|||
return BuildAuthorityKeyIdentifier(issuer.SubjectName, issuer.GetSerialNumber(), ski);
|
||||
}
|
||||
|
||||
private static X509Extension BuildX509CRLDistributionPoints(
|
||||
string distributionPoint
|
||||
)
|
||||
{
|
||||
var context0 = new Asn1Tag(TagClass.ContextSpecific, 0, true);
|
||||
Asn1Tag distributionPointChoice = context0;
|
||||
Asn1Tag fullNameChoice = context0;
|
||||
Asn1Tag generalNameUriChoice = new Asn1Tag(TagClass.ContextSpecific, 6);
|
||||
|
||||
using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
|
||||
{
|
||||
writer.PushSequence();
|
||||
writer.PushSequence();
|
||||
writer.PushSequence(distributionPointChoice);
|
||||
writer.PushSequence(fullNameChoice);
|
||||
writer.WriteCharacterString(
|
||||
generalNameUriChoice,
|
||||
UniversalTagNumber.IA5String,
|
||||
distributionPoint);
|
||||
writer.PopSequence(fullNameChoice);
|
||||
writer.PopSequence(distributionPointChoice);
|
||||
writer.PopSequence();
|
||||
writer.PopSequence();
|
||||
return new X509Extension("2.5.29.31", writer.Encode(), false);
|
||||
}
|
||||
}
|
||||
|
||||
private static X509Extension BuildAuthorityKeyIdentifier(
|
||||
X500DistinguishedName issuerName,
|
||||
byte[] issuerSerialNumber,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
@ -22,8 +22,8 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Runtime
|
|||
ICorsConfig, IClientConfig, ISwaggerConfig
|
||||
{
|
||||
// services config
|
||||
private const string OpcVaultKey = "OpcVault";
|
||||
private const string SwaggerKey = "Swagger";
|
||||
private const string _opcVaultKey = "OpcVault";
|
||||
private const string _swaggerKey = "Swagger";
|
||||
|
||||
/// <summary>
|
||||
/// Configuration constructor
|
||||
|
@ -44,9 +44,9 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Runtime
|
|||
IConfigurationRoot configuration) :
|
||||
base(processId, configuration) {
|
||||
ServicesConfig = new ServicesConfig();
|
||||
configuration.Bind(OpcVaultKey, ServicesConfig);
|
||||
configuration.Bind(_opcVaultKey, ServicesConfig);
|
||||
SwaggerConfig = new SwaggerConfig();
|
||||
configuration.Bind(SwaggerKey, SwaggerConfig);
|
||||
configuration.Bind(_swaggerKey, SwaggerConfig);
|
||||
_auth = new AuthConfig(configuration, serviceId);
|
||||
_cors = new CorsConfig(configuration);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
|
||||
using Microsoft.Azure.IIoT.Utils;
|
||||
|
||||
namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Runtime
|
||||
{
|
||||
|
@ -13,6 +12,8 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Runtime
|
|||
string KeyVaultBaseUrl { get; set; }
|
||||
string KeyVaultResourceId { get; set; }
|
||||
string CosmosDBEndpoint { get; set; }
|
||||
string CosmosDBDatabase { get; set; }
|
||||
string CosmosDBCollection { get; set; }
|
||||
string CosmosDBToken { get; set; }
|
||||
bool AutoApprove { get; set; }
|
||||
}
|
||||
|
@ -23,6 +24,8 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Runtime
|
|||
public ServicesConfig()
|
||||
{
|
||||
KeyVaultResourceId = "https://vault.azure.net";
|
||||
CosmosDBDatabase = "OpcVault";
|
||||
CosmosDBCollection = "AppsAndCertRequests";
|
||||
AutoApprove = false;
|
||||
}
|
||||
|
||||
|
@ -33,6 +36,10 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Runtime
|
|||
/// <inheritdoc/>
|
||||
public string CosmosDBEndpoint { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public string CosmosDBDatabase { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public string CosmosDBCollection { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public string CosmosDBToken { get; set; }
|
||||
/// <inheritdoc/>
|
||||
public bool AutoApprove { get; set; }
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
//
|
||||
// "CosmosDBEndpoint": "",
|
||||
// "CosmosDBToken": ""
|
||||
// name of database, default "OpcVault"
|
||||
// "CosmosDBDatabase": ""
|
||||
// name of collection, default "AppsAndCertRequests"
|
||||
// "CosmosDBCollection": ""
|
||||
},
|
||||
|
||||
//
|
||||
|
@ -82,7 +86,7 @@
|
|||
//
|
||||
"Swagger": {
|
||||
// Swagger needs an app registration.
|
||||
"Enabled": true
|
||||
// "Enabled": true
|
||||
//
|
||||
// The application id as registered in AAS. Retrieve from portal
|
||||
// as a guid, e.g. fa01ade2-2365-4dd1-a084-a6ef027090fc
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
@ -20,13 +20,13 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
[Authorize(Policy = Policies.CanRead)]
|
||||
public sealed class CertificateGroupController : Controller
|
||||
{
|
||||
private readonly ICertificateGroup certificateGroups;
|
||||
private readonly ICertificateGroup _certificateGroups;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public CertificateGroupController(
|
||||
ICertificateGroup certificateGroups)
|
||||
{
|
||||
this.certificateGroups = certificateGroups;
|
||||
this._certificateGroups = certificateGroups;
|
||||
}
|
||||
|
||||
/// <returns>List of certificate groups</returns>
|
||||
|
@ -34,7 +34,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
[SwaggerOperation(OperationId = "GetCertificateGroupIds")]
|
||||
public async Task<CertificateGroupListApiModel> GetAsync()
|
||||
{
|
||||
return new CertificateGroupListApiModel(await this.certificateGroups.GetCertificateGroupIds());
|
||||
return new CertificateGroupListApiModel(await this._certificateGroups.GetCertificateGroupIds());
|
||||
}
|
||||
|
||||
/// <summary>Get group configuration</summary>
|
||||
|
@ -44,7 +44,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
{
|
||||
return new CertificateGroupConfigurationApiModel(
|
||||
groupId,
|
||||
await this.certificateGroups.GetCertificateGroupConfiguration(groupId));
|
||||
await this._certificateGroups.GetCertificateGroupConfiguration(groupId));
|
||||
}
|
||||
|
||||
/// <summary>Update group configuration</summary>
|
||||
|
@ -53,7 +53,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
[Authorize(Policy = Policies.CanManage)]
|
||||
public async Task<CertificateGroupConfigurationApiModel> PutAsync(string groupId, [FromBody] CertificateGroupConfigurationApiModel config)
|
||||
{
|
||||
var onBehalfOfCertificateGroups = await this.certificateGroups.OnBehalfOfRequest(Request);
|
||||
var onBehalfOfCertificateGroups = await this._certificateGroups.OnBehalfOfRequest(Request);
|
||||
return new CertificateGroupConfigurationApiModel(
|
||||
groupId,
|
||||
await onBehalfOfCertificateGroups.UpdateCertificateGroupConfiguration(groupId, config.ToServiceModel()));
|
||||
|
@ -66,7 +66,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
|
||||
public async Task<CertificateGroupConfigurationApiModel> PostAsync(string groupId, string subject, string certType)
|
||||
{
|
||||
var onBehalfOfCertificateGroups = await this.certificateGroups.OnBehalfOfRequest(Request);
|
||||
var onBehalfOfCertificateGroups = await this._certificateGroups.OnBehalfOfRequest(Request);
|
||||
return new CertificateGroupConfigurationApiModel(
|
||||
groupId,
|
||||
await onBehalfOfCertificateGroups.CreateCertificateGroupConfiguration(groupId, subject, certType));
|
||||
|
@ -78,7 +78,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
public async Task<CertificateGroupConfigurationCollectionApiModel> GetConfigAsync()
|
||||
{
|
||||
return new CertificateGroupConfigurationCollectionApiModel(
|
||||
await this.certificateGroups.GetCertificateGroupConfigurationCollection());
|
||||
await this._certificateGroups.GetCertificateGroupConfigurationCollection());
|
||||
}
|
||||
|
||||
/// <summary>Get CA Certificate chain</summary>
|
||||
|
@ -87,7 +87,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
public async Task<X509Certificate2CollectionApiModel> GetCACertificateChainAsync(string groupId, int? maxResults)
|
||||
{
|
||||
return new X509Certificate2CollectionApiModel(
|
||||
await this.certificateGroups.GetCACertificateChainAsync(groupId));
|
||||
await this._certificateGroups.GetCACertificateChainAsync(groupId));
|
||||
}
|
||||
|
||||
/// <summary>Get CA Certificate chain</summary>
|
||||
|
@ -96,7 +96,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
public async Task<X509Certificate2CollectionApiModel> GetCACertificateChainNextAsync(string groupId, [FromBody] string nextPageLink, int? maxResults)
|
||||
{
|
||||
return new X509Certificate2CollectionApiModel(
|
||||
await this.certificateGroups.GetCACertificateChainAsync(groupId));
|
||||
await this._certificateGroups.GetCACertificateChainAsync(groupId));
|
||||
}
|
||||
|
||||
/// <summary>Get CA CRL chain</summary>
|
||||
|
@ -105,7 +105,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
public async Task<X509CrlCollectionApiModel> GetCACrlChainAsync(string groupId, int? maxResults)
|
||||
{
|
||||
return new X509CrlCollectionApiModel(
|
||||
await this.certificateGroups.GetCACrlChainAsync(groupId));
|
||||
await this._certificateGroups.GetCACrlChainAsync(groupId));
|
||||
}
|
||||
|
||||
/// <summary>Get CA CRL chain</summary>
|
||||
|
@ -114,7 +114,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
public async Task<X509CrlCollectionApiModel> GetCACrlChainNextAsync(string groupId, [FromBody] string nextPageLink, int? maxResults)
|
||||
{
|
||||
return new X509CrlCollectionApiModel(
|
||||
await this.certificateGroups.GetCACrlChainAsync(groupId));
|
||||
await this._certificateGroups.GetCACrlChainAsync(groupId));
|
||||
}
|
||||
|
||||
/// <summary>Get trust list</summary>
|
||||
|
@ -122,7 +122,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
[SwaggerOperation(OperationId = "GetTrustList")]
|
||||
public async Task<TrustListApiModel> GetTrustListAsync(string groupId, int? maxResults)
|
||||
{
|
||||
return new TrustListApiModel(await this.certificateGroups.GetTrustListAsync(groupId, maxResults, null));
|
||||
return new TrustListApiModel(await this._certificateGroups.GetTrustListAsync(groupId, maxResults, null));
|
||||
}
|
||||
|
||||
/// <summary>Get trust list</summary>
|
||||
|
@ -130,7 +130,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
[SwaggerOperation(OperationId = "GetTrustListNext")]
|
||||
public async Task<TrustListApiModel> GetTrustListNextAsync(string groupId, [FromBody] string nextPageLink, int? maxResults)
|
||||
{
|
||||
return new TrustListApiModel(await this.certificateGroups.GetTrustListAsync(groupId, maxResults, nextPageLink));
|
||||
return new TrustListApiModel(await this._certificateGroups.GetTrustListAsync(groupId, maxResults, nextPageLink));
|
||||
}
|
||||
|
||||
/// <summary>Create new CA Certificate</summary>
|
||||
|
@ -140,7 +140,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
|
||||
public async Task<X509Certificate2ApiModel> PostCreateAsync(string groupId)
|
||||
{
|
||||
var onBehalfOfCertificateGroups = await this.certificateGroups.OnBehalfOfRequest(Request);
|
||||
var onBehalfOfCertificateGroups = await this._certificateGroups.OnBehalfOfRequest(Request);
|
||||
return new X509Certificate2ApiModel(
|
||||
await onBehalfOfCertificateGroups.CreateCACertificateAsync(groupId));
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
[Authorize(Policy = Policies.CanRead)]
|
||||
public sealed class StatusController : Controller
|
||||
{
|
||||
private readonly ILogger log;
|
||||
private readonly ICertificateGroup certificateGroups;
|
||||
private readonly IApplicationsDatabase applicationDatabase;
|
||||
private readonly ILogger _log;
|
||||
private readonly ICertificateGroup _certificateGroups;
|
||||
private readonly IApplicationsDatabase _applicationDatabase;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public StatusController(
|
||||
|
@ -33,9 +33,9 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
ILogger logger
|
||||
)
|
||||
{
|
||||
this.applicationDatabase = applicationDatabase;
|
||||
this.certificateGroups = certificateGroups;
|
||||
this.log = logger;
|
||||
this._applicationDatabase = applicationDatabase;
|
||||
this._certificateGroups = certificateGroups;
|
||||
this._log = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -51,7 +51,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
string applicationMessage = "Alive and well";
|
||||
try
|
||||
{
|
||||
var apps = await applicationDatabase.QueryApplicationsAsync(0, 1, null, null, 0, null, null);
|
||||
var apps = await _applicationDatabase.QueryApplicationsAsync(0, 1, null, null, 0, null, null);
|
||||
applicationOk = apps != null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -59,13 +59,13 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
applicationOk = false;
|
||||
applicationMessage = ex.Message;
|
||||
}
|
||||
this.log.Info("Service status application database", () => new { Healthy = applicationOk, Message = applicationMessage });
|
||||
this._log.Info("Service status application database", () => new { Healthy = applicationOk, Message = applicationMessage });
|
||||
|
||||
bool kvOk;
|
||||
string kvMessage = "Alive and well";
|
||||
try
|
||||
{
|
||||
var groups = await certificateGroups.GetCertificateGroupIds();
|
||||
var groups = await _certificateGroups.GetCertificateGroupIds();
|
||||
kvOk = groups.Length > 0;
|
||||
kvMessage = String.Join(",", groups);
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.v1.Controllers
|
|||
kvOk = false;
|
||||
kvMessage = ex.Message;
|
||||
}
|
||||
this.log.Info("Service status KeyVault", () => new { Healthy = kvOk, Message = kvMessage });
|
||||
this._log.Info("Service status KeyVault", () => new { Healthy = kvOk, Message = kvMessage });
|
||||
|
||||
return new StatusApiModel(applicationOk, applicationMessage, kvOk, kvMessage);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
@ -98,32 +98,32 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Test
|
|||
[TestCaseOrderer("TestCaseOrdering.PriorityOrderer", "Microsoft.Azure.IIoT.OpcUa.Services.Vault.Test")]
|
||||
public class CertificateGroupTest
|
||||
{
|
||||
IConfigurationRoot Configuration;
|
||||
IConfigurationRoot _configuration;
|
||||
|
||||
ServicesConfig ServiceConfig = new ServicesConfig();
|
||||
IClientConfig ClientConfig = new ClientConfig();
|
||||
TraceLogger Logger = new TraceLogger(new LogConfig());
|
||||
ServicesConfig _serviceConfig = new ServicesConfig();
|
||||
IClientConfig _clientConfig = new ClientConfig();
|
||||
TraceLogger _logger = new TraceLogger(new LogConfig());
|
||||
|
||||
public CertificateGroupTest(ITestOutputHelper log)
|
||||
{
|
||||
_log = log;
|
||||
_randomSource = new RandomSource(randomStart);
|
||||
_randomSource = new RandomSource(_randomStart);
|
||||
_dataGenerator = new DataGenerator(_randomSource);
|
||||
var builder = new ConfigurationBuilder()
|
||||
.SetBasePath(Directory.GetCurrentDirectory())
|
||||
.AddJsonFile("testsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile("testsettings.Development.json", optional: true, reloadOnChange: true)
|
||||
.AddEnvironmentVariables();
|
||||
Configuration = builder.Build();
|
||||
Configuration.Bind("OpcVault", ServiceConfig);
|
||||
Configuration.Bind("Auth", ClientConfig);
|
||||
_configuration = builder.Build();
|
||||
_configuration.Bind("OpcVault", _serviceConfig);
|
||||
_configuration.Bind("Auth", _clientConfig);
|
||||
}
|
||||
|
||||
[SkippableFact, Trait(Constants.Type, Constants.UnitTest), TestPriority(100)]
|
||||
private async Task KeyVaultPurgeCACertificateAsync()
|
||||
{
|
||||
SkipOnInvalidConfiguration();
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(ServiceConfig, ClientConfig, Logger);
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(_serviceConfig, _clientConfig, _logger);
|
||||
await keyVault.PurgeAsync();
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Test
|
|||
public async Task KeyVaultCreateCACertificateAsync()
|
||||
{
|
||||
SkipOnInvalidConfiguration();
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(ServiceConfig, ClientConfig, Logger);
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(_serviceConfig, _clientConfig, _logger);
|
||||
string[] groups = await keyVault.GetCertificateGroupIds();
|
||||
foreach (string group in groups)
|
||||
{
|
||||
|
@ -159,7 +159,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Test
|
|||
public async Task KeyVaultInit()
|
||||
{
|
||||
SkipOnInvalidConfiguration();
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(ServiceConfig, ClientConfig, Logger);
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(_serviceConfig, _clientConfig, _logger);
|
||||
await keyVault.Init();
|
||||
}
|
||||
|
||||
|
@ -167,7 +167,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Test
|
|||
public async Task KeyVaultListOfCertGroups()
|
||||
{
|
||||
SkipOnInvalidConfiguration();
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(ServiceConfig, ClientConfig, Logger);
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(_serviceConfig, _clientConfig, _logger);
|
||||
string[] groups = await keyVault.GetCertificateGroupIds();
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Test
|
|||
public async Task KeyVaultGroupConfigurationCollection()
|
||||
{
|
||||
SkipOnInvalidConfiguration();
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(ServiceConfig, ClientConfig, Logger);
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(_serviceConfig, _clientConfig, _logger);
|
||||
Opc.Ua.Gds.Server.CertificateGroupConfigurationCollection groupCollection = await keyVault.GetCertificateGroupConfigurationCollection();
|
||||
Assert.NotNull(groupCollection);
|
||||
Assert.NotEmpty(groupCollection);
|
||||
|
@ -185,7 +185,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Test
|
|||
public async Task KeyVaultGetCertificateAsync()
|
||||
{
|
||||
SkipOnInvalidConfiguration();
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(ServiceConfig, ClientConfig, Logger);
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(_serviceConfig, _clientConfig, _logger);
|
||||
await keyVault.Init();
|
||||
string[] groups = await keyVault.GetCertificateGroupIds();
|
||||
foreach (string group in groups)
|
||||
|
@ -213,13 +213,15 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Test
|
|||
{
|
||||
SkipOnInvalidConfiguration();
|
||||
X509CertificateCollection certCollection = new X509CertificateCollection();
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(ServiceConfig, ClientConfig, Logger);
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(_serviceConfig, _clientConfig, _logger);
|
||||
string[] groups = await keyVault.GetCertificateGroupIds();
|
||||
foreach (string group in groups)
|
||||
{
|
||||
ApplicationTestData randomApp = RandomApplicationTestData();
|
||||
Guid requestId = Guid.NewGuid();
|
||||
Opc.Ua.Gds.Server.X509Certificate2KeyPair newKeyPair = await keyVault.NewKeyPairRequestAsync(
|
||||
group,
|
||||
requestId.ToString(),
|
||||
randomApp.ApplicationRecord.ApplicationUri,
|
||||
randomApp.Subject,
|
||||
randomApp.DomainNames.ToArray(),
|
||||
|
@ -250,7 +252,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Test
|
|||
{
|
||||
SkipOnInvalidConfiguration();
|
||||
X509CertificateCollection certCollection = new X509CertificateCollection();
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(ServiceConfig, ClientConfig, Logger);
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(_serviceConfig, _clientConfig, _logger);
|
||||
string[] groups = await keyVault.GetCertificateGroupIds();
|
||||
foreach (string group in groups)
|
||||
{
|
||||
|
@ -298,14 +300,16 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Test
|
|||
public async Task KeyVaultNewKeyPairAndRevokeCertificateAsync()
|
||||
{
|
||||
SkipOnInvalidConfiguration();
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(ServiceConfig, ClientConfig, Logger);
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(_serviceConfig, _clientConfig, _logger);
|
||||
await keyVault.Init();
|
||||
string[] groups = await keyVault.GetCertificateGroupIds();
|
||||
foreach (string group in groups)
|
||||
{
|
||||
ApplicationTestData randomApp = RandomApplicationTestData();
|
||||
Guid requestId = Guid.NewGuid();
|
||||
Opc.Ua.Gds.Server.X509Certificate2KeyPair newCert = await keyVault.NewKeyPairRequestAsync(
|
||||
group,
|
||||
requestId.ToString(),
|
||||
randomApp.ApplicationRecord.ApplicationUri,
|
||||
randomApp.Subject,
|
||||
randomApp.DomainNames.ToArray(),
|
||||
|
@ -332,7 +336,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Test
|
|||
public async Task GetTrustListAsync()
|
||||
{
|
||||
SkipOnInvalidConfiguration();
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(ServiceConfig, ClientConfig, Logger);
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(_serviceConfig, _clientConfig, _logger);
|
||||
await keyVault.Init();
|
||||
string[] groups = await keyVault.GetCertificateGroupIds();
|
||||
foreach (string group in groups)
|
||||
|
@ -364,7 +368,7 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Test
|
|||
}
|
||||
}
|
||||
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(ServiceConfig, ClientConfig, Logger);
|
||||
KeyVaultCertificateGroup keyVault = new KeyVaultCertificateGroup(_serviceConfig, _clientConfig, _logger);
|
||||
await keyVault.Init();
|
||||
string[] groups = await keyVault.GetCertificateGroupIds();
|
||||
|
||||
|
@ -513,17 +517,17 @@ namespace Microsoft.Azure.IIoT.OpcUa.Services.Vault.Test
|
|||
private void SkipOnInvalidConfiguration()
|
||||
{
|
||||
Skip.If(
|
||||
ServiceConfig.KeyVaultBaseUrl == null ||
|
||||
ServiceConfig.KeyVaultResourceId == null ||
|
||||
ClientConfig.AppId == null ||
|
||||
ClientConfig.AppSecret == null,
|
||||
_serviceConfig.KeyVaultBaseUrl == null ||
|
||||
_serviceConfig.KeyVaultResourceId == null ||
|
||||
_clientConfig.AppId == null ||
|
||||
_clientConfig.AppSecret == null,
|
||||
"Missing valid KeyVault configuration");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>The test logger</summary>
|
||||
private readonly ITestOutputHelper _log;
|
||||
private const int randomStart = 1;
|
||||
private const int _randomStart = 1;
|
||||
private RandomSource _randomSource;
|
||||
private DataGenerator _dataGenerator;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче