public async Task FileSystemRepo_WriteAsync_CreatesExpectedFile(ScriptSecretsType secretsType) { await WriteAsync_CreatesExpectedFile(SecretsRepositoryType.FileSystem, secretsType); }
private async Task ReadAsync_ReadsExpectedFile(SecretsRepositoryType repositoryType, ScriptSecretsType secretsType) { using (var directory = new TempDirectory()) { await _fixture.TestInitialize(repositoryType, directory.Path); ScriptSecrets testSecrets = null; if (secretsType == ScriptSecretsType.Host) { testSecrets = new HostSecrets() { MasterKey = new Key("master", "test"), FunctionKeys = new List <Key>() { new Key(KeyName, "test") }, SystemKeys = new List <Key>() { new Key(KeyName, "test") } }; } else { testSecrets = new FunctionSecrets() { Keys = new List <Key>() { new Key(KeyName, "test") } }; } string testFunctionName = secretsType == ScriptSecretsType.Host ? "host" : functionName; await _fixture.WriteSecret(testFunctionName, testSecrets); var target = _fixture.GetNewSecretRepository(); ScriptSecrets secretsContent = await target.ReadAsync(secretsType, testFunctionName); if (secretsType == ScriptSecretsType.Host) { Assert.Equal((secretsContent as HostSecrets).MasterKey.Name, "master"); Assert.Equal((secretsContent as HostSecrets).MasterKey.Value, "test"); Assert.Equal((secretsContent as HostSecrets).FunctionKeys[0].Name, KeyName); Assert.Equal((secretsContent as HostSecrets).FunctionKeys[0].Value, "test"); Assert.Equal((secretsContent as HostSecrets).SystemKeys[0].Name, KeyName); Assert.Equal((secretsContent as HostSecrets).SystemKeys[0].Value, "test"); } else { Assert.Equal((secretsContent as FunctionSecrets).Keys[0].Name, KeyName); Assert.Equal((secretsContent as FunctionSecrets).Keys[0].Value, "test"); } } }
public async Task BlobStorageRepo_WriteAsync_CreatesExpectedFile(ScriptSecretsType secretsType) { await WriteAsync_CreatesExpectedFile(SecretsRepositoryType.BlobStorage, secretsType); }
public virtual Task <KeyOperationResult> AddOrUpdateFunctionSecretAsync(string secretName, string secret, string keyScope, ScriptSecretsType secretsType) { string resultSecret = secret ?? "generated"; return(Task.FromResult(new KeyOperationResult(resultSecret, OperationResult.Created))); }
public async Task KeyVaultRepo_ReadAsync_ReadsExpectedFile(ScriptSecretsType secretsType) { await ReadAsync_ReadsExpectedFile(SecretsRepositoryType.KeyVault, secretsType); }
public async Task GetSecretSnapshots_ReturnsExpected(SecretsRepositoryType repositoryType, ScriptSecretsType secretsType) { using (var directory = new TempDirectory()) { await _fixture.TestInitialize(repositoryType, directory.Path); ScriptSecrets secrets = null; if (secretsType == ScriptSecretsType.Host) { secrets = new HostSecrets() { MasterKey = new Key("master", "test") }; } else { secrets = new FunctionSecrets() { Keys = new List <Key>() { new Key(KeyName, "test") } }; } string testFunctionName = secretsType == ScriptSecretsType.Host ? null : functionName; var target = _fixture.GetNewSecretRepository(); await target.WriteAsync(secretsType, testFunctionName, secrets); for (int i = 0; i < 5; i++) { await target.WriteSnapshotAsync(secretsType, testFunctionName, secrets); } string[] files = await target.GetSecretSnapshots(secretsType, testFunctionName); Assert.True(files.Length > 0); } }
private async Task <ScriptSecrets> GetSecretBlobText(string functionNameOrHost, ScriptSecretsType type) { string blobText = null; string blobPath = RelativeBlobPath(functionNameOrHost); if (await BlobContainer.GetBlockBlobReference(blobPath).ExistsAsync()) { blobText = await BlobContainer.GetBlockBlobReference(blobPath).DownloadTextAsync(); } return(ScriptSecretSerializer.DeserializeSecrets(type, blobText)); }
public async Task <KeyOperationResult> AddOrUpdateFunctionSecretAsync(string secretName, string secret, string keyScope, ScriptSecretsType secretsType) { Func <ScriptSecrets> secretsFactory = null; if (secretsType == ScriptSecretsType.Function) { secretsFactory = () => new FunctionSecrets(new List <Key>()); } else if (secretsType == ScriptSecretsType.Host) { secretsType = ScriptSecretsType.Host; secretsFactory = GenerateHostSecrets; } else { throw new NotSupportedException($"Secrets type {secretsType.ToString("G")} not supported."); } KeyOperationResult result = await AddOrUpdateSecretAsync(secretsType, keyScope, secretName, secret, secretsFactory); _logger.LogInformation(string.Format(Resources.TraceAddOrUpdateFunctionSecret, secretsType, secretName, keyScope ?? "host", result.Result)); return(result); }
public async Task <bool> DeleteSecretAsync(string secretName, string keyScope, ScriptSecretsType secretsType) { bool deleted = await ModifyFunctionSecretAsync(secretsType, keyScope, secretName, (secrets, key) => { secrets?.RemoveKey(key, keyScope); return(secrets); }); if (deleted) { string target = secretsType == ScriptSecretsType.Function ? $"Function ('{keyScope}')" : $"Host (scope: '{keyScope}')"; _logger.LogInformation(string.Format(Resources.TraceSecretDeleted, target, secretName)); } return(deleted); }
private async Task <IActionResult> DeleteFunctionSecretAsync(string keyName, string keyScope, ScriptSecretsType secretsType) { if (keyName == null) { return(BadRequest("Invalid key name.")); } if (IsBuiltInSystemKeyName(keyName)) { // System keys cannot be deleted. return(BadRequest("Cannot delete System Key.")); } if ((secretsType == ScriptSecretsType.Function && keyScope != null && !IsFunction(keyScope)) || !await _secretManagerProvider.Current.DeleteSecretAsync(keyName, keyScope, secretsType)) { // Either the function or the key were not found return(NotFound()); } await _functionsSyncManager.TrySyncTriggersAsync(); _logger.LogDebug(string.Format(Resources.TraceKeysApiSecretChange, keyName, keyScope ?? "host", "Deleted")); return(StatusCode(StatusCodes.Status204NoContent)); }
private string GetSecretsBlobPath(ScriptSecretsType secretsType, string functionName = null) { return(secretsType == ScriptSecretsType.Host ? _hostSecretsBlobPath : string.Format("{0}/{1}", _secretsBlobPath, GetSecretFileName(functionName))); }
private async Task <IActionResult> AddOrUpdateSecretAsync(string keyName, string value, string keyScope, ScriptSecretsType secretsType) { if (secretsType == ScriptSecretsType.Function && keyScope != null && !IsFunction(keyScope)) { return(NotFound()); } KeyOperationResult operationResult; if (secretsType == ScriptSecretsType.Host && string.Equals(keyName, MasterKeyName, StringComparison.OrdinalIgnoreCase)) { operationResult = await _secretManagerProvider.Current.SetMasterKeyAsync(value); } else { operationResult = await _secretManagerProvider.Current.AddOrUpdateFunctionSecretAsync(keyName, value, keyScope, secretsType); } _logger.LogDebug(string.Format(Resources.TraceKeysApiSecretChange, keyName, keyScope ?? "host", operationResult.Result)); switch (operationResult.Result) { case OperationResult.Created: { var keyResponse = ApiModelUtility.CreateApiModel(new { name = keyName, value = operationResult.Secret }, Request); await _functionsSyncManager.TrySyncTriggersAsync(); return(Created(ApiModelUtility.GetBaseUri(Request), keyResponse)); } case OperationResult.Updated: { var keyResponse = ApiModelUtility.CreateApiModel(new { name = keyName, value = operationResult.Secret }, Request); await _functionsSyncManager.TrySyncTriggersAsync(); return(Ok(keyResponse)); } case OperationResult.NotFound: return(NotFound()); case OperationResult.Conflict: return(StatusCode(StatusCodes.Status409Conflict)); case OperationResult.Forbidden: return(StatusCode(StatusCodes.Status403Forbidden)); default: return(StatusCode(StatusCodes.Status500InternalServerError)); } }
private async Task <IActionResult> PutKeyAsync(string keyName, Key key, string keyScope, ScriptSecretsType secretsType) { if (key?.Value == null) { return(BadRequest("Invalid key value")); } return(await AddOrUpdateSecretAsync(keyName, key.Value, keyScope, secretsType)); }
private async Task <ScriptSecrets> GetSecretsFromKeyVault(string functionNameOrHost, ScriptSecretsType type) { var secretResults = await KeyVaultClient.GetSecretsAsync(GetKeyVaultBaseUrl()); if (type == ScriptSecretsType.Host) { SecretBundle masterBundle = await KeyVaultClient.GetSecretAsync(GetKeyVaultBaseUrl(), secretResults.FirstOrDefault(x => x.Identifier.Name.StartsWith("host--master")).Identifier.Name); SecretBundle functionKeyBundle = await KeyVaultClient.GetSecretAsync(GetKeyVaultBaseUrl(), secretResults.FirstOrDefault(x => x.Identifier.Name.StartsWith("host--functionKey")).Identifier.Name); SecretBundle systemKeyBundle = await KeyVaultClient.GetSecretAsync(GetKeyVaultBaseUrl(), secretResults.FirstOrDefault(x => x.Identifier.Name.StartsWith("host--systemKey")).Identifier.Name); HostSecrets hostSecrets = new HostSecrets() { FunctionKeys = new List <Key>() { new Key(GetSecretName(functionKeyBundle.SecretIdentifier.Name), functionKeyBundle.Value) }, SystemKeys = new List <Key>() { new Key(GetSecretName(systemKeyBundle.SecretIdentifier.Name), systemKeyBundle.Value) } }; hostSecrets.MasterKey = new Key("master", masterBundle.Value); return(hostSecrets); } else { SecretBundle functionKeyBundle = await KeyVaultClient.GetSecretAsync(GetKeyVaultBaseUrl(), secretResults.FirstOrDefault(x => x.Identifier.Name.StartsWith("function--")).Identifier.Name); FunctionSecrets functionSecrets = new FunctionSecrets() { Keys = new List <Key>() { new Key(GetSecretName(functionKeyBundle.SecretIdentifier.Name), functionKeyBundle.Value) } }; return(functionSecrets); } }
public async Task KeyVaultRepo_WriteAsync_CreatesExpectedFile(ScriptSecretsType secretsType) { await WriteAsync_CreatesExpectedFile(SecretsRepositoryType.KeyVault, secretsType); }
private Task <ScriptSecrets> LoadSecretsAsync(ScriptSecretsType secretsType, string keyScope) => LoadSecretsAsync(secretsType, keyScope, s => ScriptSecretSerializer.DeserializeSecrets(secretsType, s));
private async Task WriteAsync_CreatesExpectedFile(SecretsRepositoryType repositoryType, ScriptSecretsType secretsType) { using (var directory = new TempDirectory()) { await _fixture.TestInitialize(repositoryType, directory.Path); ScriptSecrets secrets = null; if (secretsType == ScriptSecretsType.Host) { secrets = new HostSecrets() { MasterKey = new Key("master", "test"), FunctionKeys = new List <Key>() { new Key(KeyName, "test") }, SystemKeys = new List <Key>() { new Key(KeyName, "test") } }; } else { secrets = new FunctionSecrets() { Keys = new List <Key>() { new Key(KeyName, "test") } }; } string testFunctionName = secretsType == ScriptSecretsType.Host ? null : functionName; var target = _fixture.GetNewSecretRepository(); await target.WriteAsync(secretsType, testFunctionName, secrets); string filePath = Path.Combine(directory.Path, $"{testFunctionName ?? "host"}.json"); if (repositoryType == SecretsRepositoryType.BlobStorage) { Assert.True(_fixture.MarkerFileExists(testFunctionName ?? "host")); } ScriptSecrets secrets1 = await _fixture.GetSecretText(testFunctionName ?? "host", secretsType); if (secretsType == ScriptSecretsType.Host) { Assert.Equal((secrets1 as HostSecrets).MasterKey.Name, "master"); Assert.Equal((secrets1 as HostSecrets).MasterKey.Value, "test"); Assert.Equal((secrets1 as HostSecrets).FunctionKeys[0].Name, KeyName); Assert.Equal((secrets1 as HostSecrets).FunctionKeys[0].Value, "test"); Assert.Equal((secrets1 as HostSecrets).SystemKeys[0].Name, KeyName); Assert.Equal((secrets1 as HostSecrets).SystemKeys[0].Value, "test"); } else { Assert.Equal((secrets1 as FunctionSecrets).Keys[0].Name, KeyName); Assert.Equal((secrets1 as FunctionSecrets).Keys[0].Value, "test"); } } }
public virtual Task <bool> DeleteSecretAsync(string secretName, string keyScope, ScriptSecretsType secretsType) { return(Task.FromResult(true)); }
public async Task <ScriptSecrets> GetSecretText(string functionNameOrHost, ScriptSecretsType type) { ScriptSecrets secrets = null; switch (RepositoryType) { case SecretsRepositoryType.FileSystem: string secretText = File.ReadAllText(SecretsFileOrSentinelPath(functionNameOrHost)); secrets = ScriptSecretSerializer.DeserializeSecrets(type, secretText); break; case SecretsRepositoryType.BlobStorage: secrets = await GetSecretBlobText(functionNameOrHost, type); break; case SecretsRepositoryType.KeyVault: secrets = await GetSecretsFromKeyVault(functionNameOrHost, type); break; default: break; } return(secrets); }
private static bool TryLoadSecrets(ScriptSecretsType secretsType, string filePath, out ScriptSecrets secrets) => TryLoadSecrets(filePath, s => ScriptSecretSerializer.DeserializeSecrets(secretsType, s), out secrets);