private async Task <string> GetValueInternalAsync(string context, string key)
        {
            ValidateInput(key);
            SqlPassContext config = DeserializeContext(context);

            string queryTemplate = "SELECT value FROM {0} WHERE name = ?";
            Dictionary <string, string> parameters = new Dictionary <string, string>
            {
                { "name", key },
            };

            string value = (string) await OpenConnectionAndExecute(config, queryTemplate, parameters, async (command) =>
            {
                using (OdbcDataReader reader = command.ExecuteReader())
                {
                    if (await reader.ReadAsync())
                    {
                        return(reader["value"].ToString());
                    }
                    else
                    {
                        throw new SecureStoreException(
                            SecureStoreException.Type.SecretNotFound,
                            Resource.ResourceManager.GetString(nameof(Resource.SecretNotFound), CultureInfo.InvariantCulture));
                    }
                }
            });

            return(config.IsEncrypted.Value ? CryptoHelper.Decrypt(value) : value);
        }
        private async Task <object> OpenConnectionAndExecute(SqlPassContext context, string queryTemplate, Dictionary <string, string> parameters, Func <OdbcCommand, Task <object> > action)
        {
            string connectionString = BuildConnectionString(context);

            using (OdbcConnection connection = new OdbcConnection(connectionString))
                using (OdbcCommandBuilder builder = new OdbcCommandBuilder())
                {
                    await connection.OpenAsync();

                    string escapedTableName = builder.QuoteIdentifier(context.TableName, connection);
                    string queryString      = string.Format(CultureInfo.InvariantCulture, queryTemplate, escapedTableName);

                    using (OdbcCommand command = new OdbcCommand(queryString, connection))
                    {
                        foreach (var key in parameters.Keys)
                        {
                            if (parameters.TryGetValue(key, out var value))
                            {
                                command.Parameters.AddWithValue($"@{key}", value);
                            }
                        }

                        return(await action(command));
                    }
                }
        }
        private async Task RemoveValueInternalAsync(string context, string key)
        {
            ValidateInput(key);
            SqlPassContext config = DeserializeContext(context);

            string queryTemplate = "DELETE FROM {0} WHERE name = ?";
            Dictionary <string, string> parameters = new Dictionary <string, string>
            {
                { "name", key },
            };

            await VerifyRowsAffected(
                async() => (int)await OpenConnectionAndExecute(config, queryTemplate, parameters, executeNonQueryAsync));
        }
        private static string BuildConnectionString(SqlPassContext context)
        {
            OdbcConnectionStringBuilder connectionStringBuilder = new OdbcConnectionStringBuilder
            {
                Driver = context.Driver,
            };

            connectionStringBuilder.Add("Server", context.Server);
            connectionStringBuilder.Add("Database", context.Database);
            connectionStringBuilder.Add("User ID", context.UserId);
            connectionStringBuilder.Add("Password", context.Password);
            connectionStringBuilder.Add("Trusted_Connection", context.TrustedConnection);
            return(connectionStringBuilder.ConnectionString);
        }
示例#5
0
        public void InitializeNonNullNonEmptySettingsInstantiatesHostSettings()
        {
            var hostSettings = new Dictionary <string, string>
            {
                { "Driver", "driver" }
            };

            var expected = new SqlPassContext
            {
                Driver    = "driver",
                TableName = SqlPassSecureStore.TableName,
            };

            subject.Initialize(hostSettings);
            subject.HostSettings.Should().BeEquivalentTo(expected);
        }
        /// <summary>
        /// Initialize the Secure Store plugin with host level appSettings settings
        /// stored in web.config under the key {Plugins.SecureStores}.{Plugin_Friendly_Name}.{SettingName}
        /// </summary>
        /// <param name="hostSettings"></param>
        public void Initialize(Dictionary <string, string> hostSettings)
        {
            if (hostSettings == null || hostSettings.Count == 0)
            {
                return;
            }

            string serialized = JsonConvert.SerializeObject(hostSettings);

            HostSettings = JsonConvert.DeserializeObject <SqlPassContext>(serialized);

            // override host settings table name if it is not set
            if (string.IsNullOrEmpty(HostSettings.TableName))
            {
                HostSettings.TableName = TableName;
            }
        }
        private async Task <string> CreateValueInternalAsync(string context, string key, string value)
        {
            ValidateInput(key);
            ValidateInput(value);
            SqlPassContext config = DeserializeContext(context);

            string queryTemplate = "INSERT INTO {0} (name, value) VALUES (?, ?)";
            Dictionary <string, string> parameters = new Dictionary <string, string>
            {
                { "name", key },
                { "value", config.IsEncrypted.Value ? CryptoHelper.Encrypt(value) : value },
            };

            await VerifyRowsAffected(
                async() => (int)await OpenConnectionAndExecute(config, queryTemplate, parameters, executeNonQueryAsync));

            return(key);
        }
        private async Task <string> UpdateValueInternalAsync(string context, string key, string oldAugmentedKey, string value)
        {
            ValidateInput(key);
            ValidateInput(oldAugmentedKey);
            ValidateInput(value);
            SqlPassContext config = DeserializeContext(context);

            string queryTemplate = "UPDATE {0} SET name = ?, value = ? WHERE name = ?";
            Dictionary <string, string> parameters = new Dictionary <string, string>
            {
                { "name", key },
                { "value", config.IsEncrypted.Value ? CryptoHelper.Encrypt(value) : value },
                { "oldName", oldAugmentedKey },
            };

            await VerifyRowsAffected(
                async() => (int)await OpenConnectionAndExecute(config, queryTemplate, parameters, executeNonQueryAsync));

            return(key);
        }
        /// <summary>
        /// Verify if a given context is supported for current secure store
        /// Tries to connect to the DB given by the context
        /// </summary>
        /// <returns></returns>
        public async Task ValidateContextAsync(string context)
        {
            // verify context is able to be deserialized
            SqlPassContext config = DeserializeContext(context);

            // verify connection can be established
            string connectionString = BuildConnectionString(config);

            using (OdbcConnection connection = new OdbcConnection(connectionString))
                using (OdbcCommandBuilder builder = new OdbcCommandBuilder())
                {
                    await connection.OpenAsync();

                    string escapedTableName = builder.QuoteIdentifier(config.TableName, connection);

                    try
                    {
                        using (OdbcCommand command = new OdbcCommand($"SELECT TOP 1 * FROM {escapedTableName}", connection))
                        {
                            await command.ExecuteReaderAsync();
                        }
                    }
                    catch (OdbcException ex)
                    {
                        if (!ex.Message.Contains($"Invalid object name '{config.TableName}'"))
                        {
                            throw;
                        }

                        string queryStringCreateTable = $@"CREATE TABLE {escapedTableName} (
                                                name varchar(96) NOT NULL PRIMARY KEY,
                                                value varchar(max) NOT NULL)";
                        using (OdbcCommand command = new OdbcCommand(queryStringCreateTable, connection))
                        {
                            await command.ExecuteNonQueryAsync();
                        }
                    }
                }
        }