Skip to content

Commit

Permalink
Multiple Subscription and Tenant Support (#32)
Browse files Browse the repository at this point in the history
* Updated discovery process to search across all subscriptions

* Updated documentation

* Updated storepath and documentation to reflect the change

* Checking for legacy store paths.  Updated tenant authorization.  Updated README.

* Updated changelong and integration manifest

* Added additional trace logs around store path parsing.

* Updated readme for clarity on usage of the Azure Cloud parameter.

* Updated documentation to reflect optional global cloud and private endpoint parameters.  Added optional TenantId to manifest.

* remove cert store creation

* Update generated README

---------

Co-authored-by: Michael Henderson <[email protected]>
Co-authored-by: Keyfactor <[email protected]>
  • Loading branch information
3 people authored Oct 23, 2023
1 parent b1a38fe commit bc72820
Show file tree
Hide file tree
Showing 18 changed files with 359 additions and 248 deletions.
6 changes: 0 additions & 6 deletions .github/workflows/keyfactor-starter-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,3 @@ jobs:
secrets:
token: ${{ secrets.SDK_SYNC_PAT }}

call-update-store-types-workflow:
needs: get-manifest-properties
if: needs.get-manifest-properties.outputs.integration_type == 'orchestrator' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
uses: Keyfactor/actions/.github/workflows/update-store-types.yml@main
secrets:
token: ${{ secrets.UPDATE_STORE_TYPES }}
1 change: 1 addition & 0 deletions AzureKeyVault.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AzureKeyVault", "AzureKeyVa
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{AB1BF579-FBD3-4F59-BBF2-7B973B9AD1DB}"
ProjectSection(SolutionItems) = preProject
CHANGELOG.md = CHANGELOG.md
integration-manifest.json = integration-manifest.json
readme_source.md = readme_source.md
EndProjectSection
Expand Down
22 changes: 9 additions & 13 deletions AzureKeyVault/AkvProperties.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
// Copyright 2023 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using System.Collections.Generic;

namespace Keyfactor.Extensions.Orchestrator.AzureKeyVault
{
Expand All @@ -22,9 +17,10 @@ public class AkvProperties
public string TenantId { get; set; }
public string ResourceGroupName { get; set; }
public string VaultName { get; set; }
public string StorePath { get; set; }
public string StorePath { get; set; } // format = <subscription id>:<resource group name>:<vault name>
public string VaultRegion { get; set; }
public bool PremiumSKU { get; set; }
public List<string> TenantIdsForDiscovery { get; set; }
internal protected bool UseAzureManagedIdentity
{
get
Expand Down
186 changes: 123 additions & 63 deletions AzureKeyVault/AzureClient.cs

Large diffs are not rendered by default.

17 changes: 5 additions & 12 deletions AzureKeyVault/Constants.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
// Copyright 2023 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

namespace Keyfactor.Extensions.Orchestrator.AzureKeyVault
{
Expand Down
17 changes: 5 additions & 12 deletions AzureKeyVault/JobAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
// Copyright 2023 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using System;

Expand Down
99 changes: 76 additions & 23 deletions AzureKeyVault/Jobs/AzureKeyVaultJob.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
// Copyright 2023 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using System;
using System.Collections.Generic;
using Keyfactor.Orchestrators.Extensions;
using Keyfactor.Orchestrators.Extensions.Interfaces;
using Microsoft.Extensions.Logging;
Expand All @@ -35,7 +29,7 @@ public void InitializeStore(dynamic config)
try
{
VaultProperties = new AkvProperties();
if (config.GetType().GetProperty("ClientMachine") != null)
if (config.GetType().GetProperty("ClientMachine") != null) // Discovery job
VaultProperties.TenantId = config.ClientMachine;

// ClientId can be omitted for system assigned managed identities, required for user assigned or service principal auth
Expand All @@ -44,25 +38,84 @@ public void InitializeStore(dynamic config)
// ClientSecret can be omitted for managed identities, required for service principal auth
VaultProperties.ClientSecret = PAMUtilities.ResolvePAMField(PamSecretResolver, logger, "Server Password", config.ServerPassword);

if (config.GetType().GetProperty("CertificateStoreDetails") != null)
if (config.GetType().GetProperty("CertificateStoreDetails") != null) // anything except a discovery job
{
VaultProperties.StorePath = config.CertificateStoreDetails?.StorePath;
dynamic properties = JsonConvert.DeserializeObject(config.CertificateStoreDetails.Properties.ToString());
VaultProperties.TenantId = config.CertificateStoreDetails?.ClientMachine != null ? config.CertificateStoreDetails?.ClientMachine : VaultProperties.TenantId;
VaultProperties.TenantId = VaultProperties.TenantId ?? properties.dirs;
VaultProperties.ResourceGroupName = properties.ResourceGroupName;
VaultProperties.VaultName = properties.VaultName;
VaultProperties.PremiumSKU = properties.SkuType == "premium";
VaultProperties.VaultRegion = properties.VaultRegion ?? "eastus";
VaultProperties.VaultRegion = VaultProperties.VaultRegion.ToLower();

// get the values from the storepath field. format is <subscription id>:<resource group name>:<vault name>
var storePathFields = VaultProperties.StorePath.Split(":");

if (storePathFields.Length == 3)
{ //using the latest (3 fields)
logger.LogTrace($"storepath split by `:` into 3 parts. {storePathFields}. Using Using {{subscription id}}:{{resource group name}}:{{vault name}} format.");
VaultProperties.SubscriptionId = storePathFields[0].Trim();
VaultProperties.ResourceGroupName = storePathFields[1].Trim();
VaultProperties.VaultName = storePathFields[2]?.Trim();
}

// support legacy store path <subscription id>:<vault name>
if (storePathFields.Length == 2)
{ // using previous version (2 fields)
logger.LogTrace($"storepath split by `:` into 2 parts. {storePathFields}. Using {{subscription id}}:{{vault name}} format.");
VaultProperties.SubscriptionId = storePathFields[0].Trim();
VaultProperties.VaultName = storePathFields[0].Trim();
VaultProperties.SubscriptionId = properties.SubscriptionId;
}

// support legacy store path <full azure resource identifier>
// - example: /subscriptions/b3114ff1-bb92-45b6-9bd6-e4a1eed8c91e/resourceGroups/azure_sentinel_evaluation/providers/Microsoft.KeyVault/vaults/jv2-vault
if (storePathFields.Length == 1)
{
var legacyPathComponents = VaultProperties.StorePath.Split('/', StringSplitOptions.RemoveEmptyEntries);
if (legacyPathComponents.Length == 8) // they are using the full resource path
{
logger.LogTrace($"storepath split by `/`. {storePathFields}. Using {{subscription id}}:{{vault name}} format.");
VaultProperties.SubscriptionId = legacyPathComponents[1];
VaultProperties.ResourceGroupName = legacyPathComponents[3];
VaultProperties.VaultName = legacyPathComponents[7];
}
}

VaultProperties.SubscriptionId = properties.SubscriptionId ?? VaultProperties.SubscriptionId;
VaultProperties.ResourceGroupName = properties.ResourceGroupName ?? VaultProperties.ResourceGroupName;
VaultProperties.VaultName = properties.VaultName ?? VaultProperties.VaultName; // check the field in case of legacy paths.
VaultProperties.TenantId = VaultProperties.TenantId ?? config.CertificateStoreDetails?.ClientMachine; // Client Machine could be null in the case of managed identity. That's ok.

string skuType = properties.SkuType;
VaultProperties.PremiumSKU = skuType?.ToLower() == "premium";
VaultProperties.VaultRegion = properties.VaultRegion;
VaultProperties.VaultRegion = VaultProperties.VaultRegion?.ToLower();
}
else // discovery job : Discovery only works on the Global Public Azure cloud because we do not have a way to pass the Azure Cloud instance value during a discovery job.
{
logger.LogTrace("Discovery job - getting tenant ids from directories to search field.");
VaultProperties.TenantIdsForDiscovery = new List<string>();
var dirs = config.JobProperties?["dirs"] as string;
logger.LogTrace($"Directories to search: {dirs}");

if (!string.IsNullOrEmpty(dirs))
{
// parse the list of tenant ids to perform discovery on
VaultProperties.TenantIdsForDiscovery.AddRange(dirs.Split(','));
}
else
{
// if it is empty, we use the default provided Tenant Id only
VaultProperties.TenantIdsForDiscovery.Add(VaultProperties.TenantId);
}

VaultProperties.TenantIdsForDiscovery.ForEach(tId => tId = tId.Trim());
VaultProperties.TenantId = VaultProperties.TenantId ?? VaultProperties.TenantIdsForDiscovery[0];
}
AzClient ??= new AzureClient(VaultProperties);
}
catch (Exception ex) {
catch (Exception ex)
{
logger.LogError("Error initializing store", ex.Message);
throw;
}
}
}
}
}

17 changes: 5 additions & 12 deletions AzureKeyVault/Jobs/Discovery.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
// Copyright 2023 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using System;
using System.Collections.Generic;
Expand Down
17 changes: 5 additions & 12 deletions AzureKeyVault/Jobs/Inventory.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
// Copyright 2023 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using System;
using System.Collections.Generic;
Expand Down
17 changes: 5 additions & 12 deletions AzureKeyVault/Jobs/Management.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
// Copyright 2023 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using System;
using System.Linq;
Expand Down
3 changes: 1 addition & 2 deletions AzureKeyVault/PamUtilities.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

// Copyright 2023 Keyfactor
// Copyright 2023 Keyfactor
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
Expand Down
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@

- 3.1
- Updated the Discovery job to support multiple tenants and all accessible subscriptions they contain
- Added more detailed trace logging during the discovery process
- Changed store path to be `subscription id : resource group name : vault name`
- Removed redundant Vault Name and Resource Group Name fields
- Updated documentation to explain when optional fields can be omitted from the store type definition
- Added support for legacy store paths on existing stores

- 3.0
- Added support for Azure clouds other than US public.
- Shortened Store path to `subscription id : vault name`
Expand All @@ -10,6 +19,6 @@
- Added support for Azure Managed Identity authentication
- Updated Azure client libraries
- Removed ObjectId parameter from StoreType definition
- Added SkuType and VaultRegion parameters to support vault creation from the platform.
- Added SkuType and VaultRegion parameters to support vault creation from the platform

- 1.05
Binary file modified Images/discovery-result.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Images/resource-id.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Images/storepath.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit bc72820

Please sign in to comment.