Use C# 6 string interpolation feature

Provides cleanup in logging and removes calls to String.Format
This commit is contained in:
Levi B 2015-03-16 18:45:31 -07:00
parent 0966e37d94
commit 4365b531d8
18 changed files with 152 additions and 81 deletions

View File

@ -113,7 +113,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption
if (logger.IsVerboseLevelEnabled()) if (logger.IsVerboseLevelEnabled())
{ {
logger.LogVerbose("Opening CNG algorithm '{0}' from provider '{1}' with HMAC.", HashAlgorithm, HashAlgorithmProvider); logger.LogVerboseF($"Opening CNG algorithm '{HashAlgorithm}' from provider '{HashAlgorithmProvider}' with HMAC.");
} }
BCryptAlgorithmHandle algorithmHandle = null; BCryptAlgorithmHandle algorithmHandle = null;
@ -154,7 +154,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption
if (logger.IsVerboseLevelEnabled()) if (logger.IsVerboseLevelEnabled())
{ {
logger.LogVerbose("Opening CNG algorithm '{0}' from provider '{1}' with chaining mode CBC.", EncryptionAlgorithm, EncryptionAlgorithmProvider); logger.LogVerboseF($"Opening CNG algorithm '{EncryptionAlgorithm}' from provider '{EncryptionAlgorithmProvider}' with chaining mode CBC.");
} }
BCryptAlgorithmHandle algorithmHandle = null; BCryptAlgorithmHandle algorithmHandle = null;

View File

@ -94,7 +94,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption
if (logger.IsVerboseLevelEnabled()) if (logger.IsVerboseLevelEnabled())
{ {
logger.LogVerbose("Opening CNG algorithm '{0}' from provider '{1}' with chaining mode GCM.", EncryptionAlgorithm, EncryptionAlgorithmProvider); logger.LogVerboseF($"Opening CNG algorithm '{EncryptionAlgorithm}' from provider '{EncryptionAlgorithmProvider}' with chaining mode GCM.");
} }
// Special-case cached providers // Special-case cached providers

View File

@ -88,7 +88,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption
if (logger.IsVerboseLevelEnabled()) if (logger.IsVerboseLevelEnabled())
{ {
logger.LogVerbose("Using managed keyed hash algorithm '{0}'.", ValidationAlgorithmType.FullName); logger.LogVerboseF($"Using managed keyed hash algorithm '{ValidationAlgorithmType.FullName}'.");
} }
if (ValidationAlgorithmType == typeof(HMACSHA256)) if (ValidationAlgorithmType == typeof(HMACSHA256))
@ -120,7 +120,7 @@ namespace Microsoft.AspNet.DataProtection.AuthenticatedEncryption
if (logger.IsVerboseLevelEnabled()) if (logger.IsVerboseLevelEnabled())
{ {
logger.LogVerbose("Using managed symmetric algorithm '{0}'.", EncryptionAlgorithmType.FullName); logger.LogVerboseF($"Using managed symmetric algorithm '{EncryptionAlgorithmType.FullName}'.");
} }
if (EncryptionAlgorithmType == typeof(Aes)) if (EncryptionAlgorithmType == typeof(Aes))

View File

@ -43,7 +43,7 @@ namespace Microsoft.Framework.DependencyInjection
{ {
if (log.IsInformationLevelEnabled()) if (log.IsInformationLevelEnabled())
{ {
log.LogInformation("Azure Web Sites environment detected. Using '{0}' as key repository; keys will not be encrypted at rest.", azureWebSitesKeysFolder.FullName); log.LogInformationF($"Azure Web Sites environment detected. Using '{azureWebSitesKeysFolder.FullName}' as key repository; keys will not be encrypted at rest.");
} }
// Cloud DPAPI isn't yet available, so we don't encrypt keys at rest. // Cloud DPAPI isn't yet available, so we don't encrypt keys at rest.
@ -68,11 +68,11 @@ namespace Microsoft.Framework.DependencyInjection
{ {
if (keyEncryptorDescriptor != null) if (keyEncryptorDescriptor != null)
{ {
log.LogInformation("User profile is available. Using '{0}' as key repository and Windows DPAPI to encrypt keys at rest.", localAppDataKeysFolder.FullName); log.LogInformationF($"User profile is available. Using '{localAppDataKeysFolder.FullName}' as key repository and Windows DPAPI to encrypt keys at rest.");
} }
else else
{ {
log.LogInformation("User profile is available. Using '{0}' as key repository; keys will not be encrypted at rest.", localAppDataKeysFolder.FullName); log.LogInformationF($"User profile is available. Using '{localAppDataKeysFolder.FullName}' as key repository; keys will not be encrypted at rest.");
} }
} }
} }
@ -93,11 +93,11 @@ namespace Microsoft.Framework.DependencyInjection
{ {
if (keyEncryptorDescriptor != null) if (keyEncryptorDescriptor != null)
{ {
log.LogInformation("User profile not available. Using '{0}' as key repository and Windows DPAPI to encrypt keys at rest.", regKeyStorageKey.Name); log.LogInformationF($"User profile not available. Using '{regKeyStorageKey.Name}' as key repository and Windows DPAPI to encrypt keys at rest.");
} }
else else
{ {
log.LogInformation("User profile not available. Using '{0}' as key repository; keys will not be encrypted at rest.", regKeyStorageKey.Name); log.LogInformationF($"User profile not available. Using '{regKeyStorageKey.Name}' as key repository; keys will not be encrypted at rest.");
} }
} }
} }

View File

@ -62,7 +62,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
{ {
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Considering key '{0:D}' with expiration date {1:u} as default key.", preferredDefaultKey.KeyId, preferredDefaultKey.ExpirationDate); _logger.LogVerboseF($"Considering key {preferredDefaultKey.KeyId:B} with expiration date {preferredDefaultKey.ExpirationDate:u} as default key.");
} }
// if the key has been revoked or is expired, it is no longer a candidate // if the key has been revoked or is expired, it is no longer a candidate
@ -70,7 +70,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
{ {
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Key '{0:D}' is no longer under consideration as default key because it is expired or revoked.", preferredDefaultKey.KeyId); _logger.LogVerboseF($"Key {preferredDefaultKey.KeyId:B} is no longer under consideration as default key because it is expired or revoked.");
} }
preferredDefaultKey = null; preferredDefaultKey = null;
} }

View File

@ -63,6 +63,11 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
newPurpose: purpose); newPurpose: purpose);
} }
private static string JoinPurposesForLog(IEnumerable<string> purposes)
{
return "(" + String.Join(", ", purposes.Select(p => "'" + p + "'")) + ")";
}
// allows decrypting payloads whose keys have been revoked // allows decrypting payloads whose keys have been revoked
public byte[] DangerousUnprotect(byte[] protectedData, bool ignoreRevocationErrors, out bool requiresMigration, out bool wasRevoked) public byte[] DangerousUnprotect(byte[] protectedData, bool ignoreRevocationErrors, out bool requiresMigration, out bool wasRevoked)
{ {
@ -97,8 +102,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
if (_logger.IsDebugLevelEnabled()) if (_logger.IsDebugLevelEnabled())
{ {
_logger.LogDebug("Performing protect operation to key '{0:D}' with purposes ({1}).", _logger.LogDebugF($"Performing protect operation to key {defaultKeyId:B} with purposes {JoinPurposesForLog(Purposes)}.");
defaultKeyId, String.Join(", ", Purposes.Select(p => "'" + p + "'")));
} }
// We'll need to apply the default key id to the template if it hasn't already been applied. // We'll need to apply the default key id to the template if it hasn't already been applied.
@ -218,8 +222,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
if (_logger.IsDebugLevelEnabled()) if (_logger.IsDebugLevelEnabled())
{ {
_logger.LogDebug("Performing unprotect operation to key '{0:D}' with purposes ({1}).", _logger.LogDebugF($"Performing unprotect operation to key {keyIdFromPayload:B} with purposes {JoinPurposesForLog(Purposes)}.");
keyIdFromPayload, String.Join(", ", Purposes.Select(p => "'" + p + "'")));
} }
// Find the correct encryptor in the keyring. // Find the correct encryptor in the keyring.
@ -228,9 +231,9 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
var requestedEncryptor = currentKeyRing.GetAuthenticatedEncryptorByKeyId(keyIdFromPayload, out keyWasRevoked); var requestedEncryptor = currentKeyRing.GetAuthenticatedEncryptorByKeyId(keyIdFromPayload, out keyWasRevoked);
if (requestedEncryptor == null) if (requestedEncryptor == null)
{ {
if (_logger.IsWarningLevelEnabled()) if (_logger.IsDebugLevelEnabled())
{ {
_logger.LogWarning("Key '{0:D}' was not found in the key ring. Unprotect operation cannot proceed.", keyIdFromPayload); _logger.LogDebugF($"Key {keyIdFromPayload:B} was not found in the key ring. Unprotect operation cannot proceed.");
} }
throw Error.Common_KeyNotFound(keyIdFromPayload); throw Error.Common_KeyNotFound(keyIdFromPayload);
} }
@ -247,17 +250,17 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
{ {
if (allowOperationsOnRevokedKeys) if (allowOperationsOnRevokedKeys)
{ {
if (_logger.IsWarningLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogWarning("Key '{0:D}' was revoked. Caller requested unprotect operation proceed regardless.", keyIdFromPayload); _logger.LogVerboseF($"Key {keyIdFromPayload:B} was revoked. Caller requested unprotect operation proceed regardless.");
} }
status = UnprotectStatus.DecryptionKeyWasRevoked; status = UnprotectStatus.DecryptionKeyWasRevoked;
} }
else else
{ {
if (_logger.IsWarningLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogWarning("Key '{0:D}' was revoked. Unprotect operation cannot proceed.", keyIdFromPayload); _logger.LogVerboseF($"Key {keyIdFromPayload:B} was revoked. Unprotect operation cannot proceed.");
} }
throw Error.Common_KeyRevoked(keyIdFromPayload); throw Error.Common_KeyRevoked(keyIdFromPayload);
} }

View File

@ -82,7 +82,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
{ {
if (_logger.IsWarningLevelEnabled()) if (_logger.IsWarningLevelEnabled())
{ {
_logger.LogWarning("Policy resolution states that a new key should be added to the key ring, but automatic generation of keys is disabled. Using fallback key '{0:D}' with expiration {1:u} as default key.", keyToUse.KeyId, keyToUse.ExpirationDate); _logger.LogWarningF($"Policy resolution states that a new key should be added to the key ring, but automatic generation of keys is disabled. Using fallback key {keyToUse.KeyId:B} with expiration {keyToUse.ExpirationDate:u} as default key.");
} }
return CreateCacheableKeyRingCoreStep2(now, cacheExpirationToken, keyToUse, allKeys); return CreateCacheableKeyRingCoreStep2(now, cacheExpirationToken, keyToUse, allKeys);
} }
@ -111,7 +111,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Using key '{0:D}' as the default key.", defaultKey.KeyId); _logger.LogVerboseF($"Using key {defaultKey.KeyId:B} as the default key.");
} }
DateTimeOffset nextAutoRefreshTime = now + GetRefreshPeriodWithJitter(_keyManagementOptions.KeyRingRefreshPeriod); DateTimeOffset nextAutoRefreshTime = now + GetRefreshPeriodWithJitter(_keyManagementOptions.KeyRingRefreshPeriod);

View File

@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@ -19,6 +18,8 @@ using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
using static System.FormattableString;
namespace Microsoft.AspNet.DataProtection.KeyManagement namespace Microsoft.AspNet.DataProtection.KeyManagement
{ {
/// <summary> /// <summary>
@ -168,7 +169,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
// Skip unknown elements. // Skip unknown elements.
if (_logger.IsWarningLevelEnabled()) if (_logger.IsWarningLevelEnabled())
{ {
_logger.LogWarning("Unknown element with name '{0}' found in keyring, skipping.", element.Name); _logger.LogWarningF($"Unknown element with name '{element.Name}' found in keyring, skipping.");
} }
} }
} }
@ -185,14 +186,14 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
key.SetRevoked(); key.SetRevoked();
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Marked key '{0:D}' as revoked in the keyring.", revokedKeyId); _logger.LogVerboseF($"Marked key {revokedKeyId:B} as revoked in the keyring.");
} }
} }
else else
{ {
if (_logger.IsWarningLevelEnabled()) if (_logger.IsWarningLevelEnabled())
{ {
_logger.LogWarning("Tried to process revocation of key '{0:D}', but no such key was found in keyring. Skipping.", revokedKeyId); _logger.LogWarningF($"Tried to process revocation of key {revokedKeyId:B}, but no such key was found in keyring. Skipping.");
} }
} }
} }
@ -208,7 +209,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
key.SetRevoked(); key.SetRevoked();
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Marked key '{0:D}' as revoked in the keyring.", key.KeyId); _logger.LogVerboseF($"Marked key {key.KeyId:B} as revoked in the keyring.");
} }
} }
} }
@ -247,7 +248,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
// Finally, create the Key instance // Finally, create the Key instance
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Found key '{0:D}'.", keyId); _logger.LogVerboseF($"Found key {keyId:B}.");
} }
return new Key( return new Key(
keyId: keyId, keyId: keyId,
@ -264,19 +265,15 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
{ {
if (_logger.IsWarningLevelEnabled()) if (_logger.IsWarningLevelEnabled())
{ {
_logger.LogWarning("An exception of type '{0}' occurred while processing the key element '{1}', so the key will not be included in the keyring." + Environment.NewLine _logger.LogWarningF($"An exception of type '{ex.GetType().FullName}' occurred while processing the key element '{keyElement.WithoutChildNodes()}', so the key will not be included in the keyring. Full details of the exception will be written to the 'Debug' log.");
+ "Full details of the exception will be written to the 'Debug' log.",
ex.GetType().FullName, keyElement.WithoutChildNodes());
} }
_logger.LogDebug(ex, "An exception occurred while processing the key element '{0}'.", keyElement); _logger.LogDebugF(ex, $"An exception occurred while processing the key element '{keyElement}'.");
} }
else else
{ {
if (_logger.IsWarningLevelEnabled()) if (_logger.IsWarningLevelEnabled())
{ {
_logger.LogWarning("An exception of type '{0}' occurred while processing the key element '{1}', so the key will not be included in the keyring." + Environment.NewLine _logger.LogWarningF($"An exception of type '{ex.GetType().FullName}' occurred while processing the key element '{keyElement.WithoutChildNodes()}', so the key will not be included in the keyring. To prevent accidental disclosure of sensitive information the full exception details are not being logged. To enable logging full exception details, enable 'Debug' level logging for this provider.");
+ "To prevent accidental disclosure of sensitive information the full exception details are not being logged. To enable logging full exception details, enable 'Debug' level logging for this provider.",
ex.GetType().FullName, keyElement.WithoutChildNodes());
} }
} }
@ -299,7 +296,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
DateTimeOffset massRevocationDate = (DateTimeOffset)revocationElement.Element(RevocationDateElementName); DateTimeOffset massRevocationDate = (DateTimeOffset)revocationElement.Element(RevocationDateElementName);
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Found revocation of all keys created prior to {0:u}.", massRevocationDate); _logger.LogVerboseF($"Found revocation of all keys created prior to {massRevocationDate:u}.");
} }
return massRevocationDate; return massRevocationDate;
} }
@ -309,7 +306,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
Guid keyId = XmlConvert.ToGuid(keyIdAsString); Guid keyId = XmlConvert.ToGuid(keyIdAsString);
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Found revocation of key '{0:D}'.", keyId); _logger.LogVerboseF($"Found revocation of key {keyId:B}.");
} }
return keyId; return keyId;
} }
@ -320,7 +317,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
// revocation information. // revocation information.
if (_logger.IsErrorLevelEnabled()) if (_logger.IsErrorLevelEnabled())
{ {
_logger.LogError(ex, "An exception occurred while processing the revocation element '{0}'. Cannot continue keyring processing.", revocationElement); _logger.LogErrorF(ex, $"An exception occurred while processing the revocation element '{revocationElement}'. Cannot continue keyring processing.");
} }
throw; throw;
} }
@ -337,7 +334,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
if (_logger.IsInformationLevelEnabled()) if (_logger.IsInformationLevelEnabled())
{ {
_logger.LogInformation("Revoking all keys as of {0:u} for reason '{1}'.", revocationDate, reason); _logger.LogInformationF($"Revoking all keys as of {revocationDate:u} for reason '{reason}'.");
} }
var revocationElement = new XElement(RevocationElementName, var revocationElement = new XElement(RevocationElementName,
@ -366,7 +363,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
{ {
if (!suppressLogging && _logger.IsVerboseLevelEnabled()) if (!suppressLogging && _logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Key cache expiration token triggered by '{0}' operation.", opName); _logger.LogVerboseF($"Key cache expiration token triggered by '{opName}' operation.");
} }
Interlocked.Exchange(ref _cacheExpirationTokenSource, new CancellationTokenSource())?.Cancel(); Interlocked.Exchange(ref _cacheExpirationTokenSource, new CancellationTokenSource())?.Cancel();
@ -385,7 +382,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
if (_logger.IsInformationLevelEnabled()) if (_logger.IsInformationLevelEnabled())
{ {
_logger.LogInformation("Creating key {0:D} with creation date {1:u}, activation date {2:u}, and expiration date {3:u}.", keyId, creationDate, activationDate, expirationDate); _logger.LogInformationF($"Creating key {keyId:B} with creation date {creationDate:u}, activation date {activationDate:u}, and expiration date {expirationDate:u}.");
} }
var newDescriptor = _authenticatedEncryptorConfiguration.CreateNewDescriptor() var newDescriptor = _authenticatedEncryptorConfiguration.CreateNewDescriptor()
@ -394,7 +391,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Descriptor deserializer type for key {0:D} is {1}.", keyId, descriptorXmlInfo.DeserializerType.AssemblyQualifiedName); _logger.LogVerboseF($"Descriptor deserializer type for key {keyId:B} is '{descriptorXmlInfo.DeserializerType.AssemblyQualifiedName}'.");
} }
// build the <key> element // build the <key> element
@ -413,11 +410,11 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
{ {
if (_keyEscrowSink != null) if (_keyEscrowSink != null)
{ {
_logger.LogVerbose("Key escrow sink found. Writing key {0:D} to escrow.", keyId); _logger.LogVerboseF($"Key escrow sink found. Writing key {keyId:B} to escrow.");
} }
else else
{ {
_logger.LogVerbose("No key escrow sink found. Not writing key {0:D} to escrow.", keyId); _logger.LogVerboseF($"No key escrow sink found. Not writing key {keyId:B} to escrow.");
} }
} }
_keyEscrowSink?.Store(keyId, keyElement); _keyEscrowSink?.Store(keyId, keyElement);
@ -425,12 +422,12 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
// If an XML encryptor has been configured, protect secret key material now. // If an XML encryptor has been configured, protect secret key material now.
if (KeyEncryptor == null && _logger.IsWarningLevelEnabled()) if (KeyEncryptor == null && _logger.IsWarningLevelEnabled())
{ {
_logger.LogWarning("No XML encryptor configured. Key {0:D} may be persisted to storage in unencrypted form.", keyId); _logger.LogWarningF($"No XML encryptor configured. Key {keyId:B} may be persisted to storage in unencrypted form.");
} }
var possiblyEncryptedKeyElement = KeyEncryptor?.EncryptIfNecessary(keyElement) ?? keyElement; var possiblyEncryptedKeyElement = KeyEncryptor?.EncryptIfNecessary(keyElement) ?? keyElement;
// Persist it to the underlying repository and trigger the cancellation token. // Persist it to the underlying repository and trigger the cancellation token.
string friendlyName = String.Format(CultureInfo.InvariantCulture, "key-{0:D}", keyId); string friendlyName = Invariant($"key-{keyId:D}");
KeyRepository.StoreElement(possiblyEncryptedKeyElement, friendlyName); KeyRepository.StoreElement(possiblyEncryptedKeyElement, friendlyName);
TriggerAndResetCacheExpirationToken(); TriggerAndResetCacheExpirationToken();
@ -453,7 +450,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
if (_logger.IsInformationLevelEnabled()) if (_logger.IsInformationLevelEnabled())
{ {
_logger.LogInformation("Revoking key {0:D} at {1:u} for reason '{2}'.", keyId, revocationDate, reason); _logger.LogInformationF($"Revoking key {keyId:B} at {revocationDate:u} for reason '{reason}'.");
} }
var revocationElement = new XElement(RevocationElementName, var revocationElement = new XElement(RevocationElementName,
@ -464,7 +461,7 @@ namespace Microsoft.AspNet.DataProtection.KeyManagement
new XElement(ReasonElementName, reason)); new XElement(ReasonElementName, reason));
// Persist it to the underlying repository and trigger the cancellation token // Persist it to the underlying repository and trigger the cancellation token
string friendlyName = String.Format(CultureInfo.InvariantCulture, "revocation-{0:D}", keyId); string friendlyName = Invariant($"revocation-{keyId:D}");
KeyRepository.StoreElement(revocationElement, friendlyName); KeyRepository.StoreElement(revocationElement, friendlyName);
TriggerAndResetCacheExpirationToken(); TriggerAndResetCacheExpirationToken();
} }

View File

@ -8,7 +8,8 @@ using Microsoft.Framework.Logging.Internal;
namespace Microsoft.Framework.Logging namespace Microsoft.Framework.Logging
{ {
/// <summary> /// <summary>
/// Helpful extension methods on ILogger. /// Helpful extension methods on <see cref="ILogger"/>.
/// Methods ending in *F take <see cref="FormattableString"/> as a parameter.
/// </summary> /// </summary>
internal static class LoggingExtensions internal static class LoggingExtensions
{ {
@ -68,19 +69,44 @@ namespace Microsoft.Framework.Logging
return (logger != null && logger.IsEnabled(level)); return (logger != null && logger.IsEnabled(level));
} }
public static void LogDebug(this ILogger logger, Exception error, string message, params object[] args) public static void LogDebugF(this ILogger logger, FormattableString message)
{ {
logger.LogDebug(new FormattedLogValues(message, args), error); logger.LogDebug(message.Format, message.GetArguments());
} }
public static void LogError(this ILogger logger, Exception error, string message, params object[] args) public static void LogDebugF(this ILogger logger, Exception error, FormattableString message)
{ {
logger.LogError(new FormattedLogValues(message, args), error); logger.LogDebug(new FormattedLogValues(message.Format, message.GetArguments()), error);
} }
public static void LogWarning(this ILogger logger, Exception error, string message, params object[] args) public static void LogError(this ILogger logger, Exception error, string message)
{ {
logger.LogWarning(new FormattedLogValues(message, args), error); logger.LogError(message, error);
}
public static void LogErrorF(this ILogger logger, Exception error, FormattableString message)
{
logger.LogError(new FormattedLogValues(message.Format, message.GetArguments()), error);
}
public static void LogInformationF(this ILogger logger, FormattableString message)
{
logger.LogInformation(message.Format, message.GetArguments());
}
public static void LogVerboseF(this ILogger logger, FormattableString message)
{
logger.LogVerbose(message.Format, message.GetArguments());
}
public static void LogWarningF(this ILogger logger, FormattableString message)
{
logger.LogWarning(message.Format, message.GetArguments());
}
public static void LogWarningF(this ILogger logger, Exception error, FormattableString message)
{
logger.LogWarning(new FormattedLogValues(message.Format, message.GetArguments()), error);
} }
} }
} }

View File

@ -107,7 +107,7 @@ namespace Microsoft.AspNet.DataProtection
} }
/// <summary> /// <summary>
/// The key '{0:D}' was not found in the key ring. /// The key {0:B} was not found in the key ring.
/// </summary> /// </summary>
internal static string Common_KeyNotFound internal static string Common_KeyNotFound
{ {
@ -115,7 +115,7 @@ namespace Microsoft.AspNet.DataProtection
} }
/// <summary> /// <summary>
/// The key '{0:D}' was not found in the key ring. /// The key {0:B} was not found in the key ring.
/// </summary> /// </summary>
internal static string FormatCommon_KeyNotFound() internal static string FormatCommon_KeyNotFound()
{ {
@ -123,7 +123,7 @@ namespace Microsoft.AspNet.DataProtection
} }
/// <summary> /// <summary>
/// The key '{0:D}' has been revoked. /// The key {0:B} has been revoked.
/// </summary> /// </summary>
internal static string Common_KeyRevoked internal static string Common_KeyRevoked
{ {
@ -131,7 +131,7 @@ namespace Microsoft.AspNet.DataProtection
} }
/// <summary> /// <summary>
/// The key '{0:D}' has been revoked. /// The key {0:B} has been revoked.
/// </summary> /// </summary>
internal static string FormatCommon_KeyRevoked() internal static string FormatCommon_KeyRevoked()
{ {
@ -235,7 +235,7 @@ namespace Microsoft.AspNet.DataProtection
} }
/// <summary> /// <summary>
/// The key '{0:D}' already exists in the keyring. /// The key {0:B} already exists in the keyring.
/// </summary> /// </summary>
internal static string XmlKeyManager_DuplicateKey internal static string XmlKeyManager_DuplicateKey
{ {
@ -243,7 +243,7 @@ namespace Microsoft.AspNet.DataProtection
} }
/// <summary> /// <summary>
/// The key '{0:D}' already exists in the keyring. /// The key {0:B} already exists in the keyring.
/// </summary> /// </summary>
internal static string FormatXmlKeyManager_DuplicateKey() internal static string FormatXmlKeyManager_DuplicateKey()
{ {

View File

@ -153,7 +153,7 @@ namespace Microsoft.AspNet.DataProtection.Repositories
{ {
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Reading data from file '{0}'.", fullPath); _logger.LogVerboseF($"Reading data from file '{fullPath}'.");
} }
using (var fileStream = File.OpenRead(fullPath)) using (var fileStream = File.OpenRead(fullPath))
@ -169,7 +169,7 @@ namespace Microsoft.AspNet.DataProtection.Repositories
string newFriendlyName = Guid.NewGuid().ToString(); string newFriendlyName = Guid.NewGuid().ToString();
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("The name '{0}' is not a safe file name, using '{1}' instead.", friendlyName, newFriendlyName); _logger.LogVerboseF($"The name '{friendlyName}' is not a safe file name, using '{newFriendlyName}' instead.");
} }
friendlyName = newFriendlyName; friendlyName = newFriendlyName;
} }
@ -198,7 +198,7 @@ namespace Microsoft.AspNet.DataProtection.Repositories
// Renames are atomic operations on the file systems we support. // Renames are atomic operations on the file systems we support.
if (_logger.IsInformationLevelEnabled()) if (_logger.IsInformationLevelEnabled())
{ {
_logger.LogInformation("Writing data to file '{0}.", finalFilename); _logger.LogInformationF($"Writing data to file '{finalFilename}'.");
} }
File.Move(tempFilename, finalFilename); File.Move(tempFilename, finalFilename);
} }

View File

@ -3,7 +3,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Security.Principal; using System.Security.Principal;
using System.Xml.Linq; using System.Xml.Linq;
@ -11,6 +10,8 @@ using Microsoft.Framework.Internal;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
using Microsoft.Win32; using Microsoft.Win32;
using static System.FormattableString;
namespace Microsoft.AspNet.DataProtection.Repositories namespace Microsoft.AspNet.DataProtection.Repositories
{ {
/// <summary> /// <summary>
@ -96,7 +97,7 @@ namespace Microsoft.AspNet.DataProtection.Repositories
// Even though this is in HKLM, WAS ensures that applications hosted in IIS are properly isolated. // Even though this is in HKLM, WAS ensures that applications hosted in IIS are properly isolated.
// See APP_POOL::EnsureSharedMachineKeyStorage in WAS source for more info. // See APP_POOL::EnsureSharedMachineKeyStorage in WAS source for more info.
// The version number will need to change if IIS hosts Core CLR directly. // The version number will need to change if IIS hosts Core CLR directly.
string aspnetAutoGenKeysBaseKeyName = String.Format(CultureInfo.InvariantCulture, @"SOFTWARE\Microsoft\ASP.NET\4.0.30319.0\AutoGenKeys\{0}", WindowsIdentity.GetCurrent().User.Value); string aspnetAutoGenKeysBaseKeyName = Invariant($@"SOFTWARE\Microsoft\ASP.NET\4.0.30319.0\AutoGenKeys\{WindowsIdentity.GetCurrent().User.Value}");
var aspnetBaseKey = hklmBaseKey.OpenSubKey(aspnetAutoGenKeysBaseKeyName, writable: true); var aspnetBaseKey = hklmBaseKey.OpenSubKey(aspnetAutoGenKeysBaseKeyName, writable: true);
if (aspnetBaseKey != null) if (aspnetBaseKey != null)
{ {
@ -132,7 +133,7 @@ namespace Microsoft.AspNet.DataProtection.Repositories
{ {
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Reading data from registry key '{0}', value '{1}'.", regKey.ToString(), valueName); _logger.LogVerboseF($"Reading data from registry key '{regKey}', value '{valueName}'.");
} }
string data = regKey.GetValue(valueName) as string; string data = regKey.GetValue(valueName) as string;
@ -146,7 +147,7 @@ namespace Microsoft.AspNet.DataProtection.Repositories
string newFriendlyName = Guid.NewGuid().ToString(); string newFriendlyName = Guid.NewGuid().ToString();
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("The name '{0}' is not a safe registry value name, using '{1}' instead.", friendlyName, newFriendlyName); _logger.LogVerboseF($"The name '{friendlyName}' is not a safe registry value name, using '{newFriendlyName}' instead.");
} }
friendlyName = newFriendlyName; friendlyName = newFriendlyName;
} }

View File

@ -136,10 +136,10 @@
<value>An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information.</value> <value>An error occurred while trying to encrypt the provided data. Refer to the inner exception for more information.</value>
</data> </data>
<data name="Common_KeyNotFound" xml:space="preserve"> <data name="Common_KeyNotFound" xml:space="preserve">
<value>The key '{0:D}' was not found in the key ring.</value> <value>The key {0:B} was not found in the key ring.</value>
</data> </data>
<data name="Common_KeyRevoked" xml:space="preserve"> <data name="Common_KeyRevoked" xml:space="preserve">
<value>The key '{0:D}' has been revoked.</value> <value>The key {0:B} has been revoked.</value>
</data> </data>
<data name="ProtectionProvider_BadMagicHeader" xml:space="preserve"> <data name="ProtectionProvider_BadMagicHeader" xml:space="preserve">
<value>The provided payload cannot be decrypted because it was not protected with this protection provider.</value> <value>The provided payload cannot be decrypted because it was not protected with this protection provider.</value>
@ -160,7 +160,7 @@
<value>The new key lifetime must be at least one week.</value> <value>The new key lifetime must be at least one week.</value>
</data> </data>
<data name="XmlKeyManager_DuplicateKey" xml:space="preserve"> <data name="XmlKeyManager_DuplicateKey" xml:space="preserve">
<value>The key '{0:D}' already exists in the keyring.</value> <value>The key {0:B} already exists in the keyring.</value>
</data> </data>
<data name="Common_ArgumentCannotBeNullOrEmpty" xml:space="preserve"> <data name="Common_ArgumentCannotBeNullOrEmpty" xml:space="preserve">
<value>Argument cannot be null or empty.</value> <value>Argument cannot be null or empty.</value>

View File

@ -0,0 +1,43 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#if !DNXCORE50
// These classes allow using the C# string interpolation feature from .NET 4.5.1.
// They're slimmed-down versions of the classes that exist in .NET 4.6.
using System.Globalization;
namespace System
{
internal struct FormattableString
{
private readonly object[] _arguments;
public readonly string Format;
internal FormattableString(string format, params object[] arguments)
{
Format = format;
_arguments = arguments;
}
public object[] GetArguments() => _arguments;
public static string Invariant(FormattableString formattable)
{
return String.Format(CultureInfo.InvariantCulture, formattable.Format, formattable.GetArguments());
}
}
}
namespace System.Runtime.CompilerServices
{
internal static class FormattableStringFactory
{
public static FormattableString Create(string format, params object[] arguments)
{
return new FormattableString(format, arguments);
}
}
}
#endif

View File

@ -132,7 +132,7 @@ namespace Microsoft.AspNet.DataProtection.XmlEncryption
{ {
if (_logger.IsErrorLevelEnabled()) if (_logger.IsErrorLevelEnabled())
{ {
_logger.LogError(ex, "An exception occurred while trying to resolve certificate with thumbprint '{0}'.", thumbprint); _logger.LogErrorF(ex, $"An exception occurred while trying to resolve certificate with thumbprint '{thumbprint}'.");
} }
throw; throw;
} }
@ -146,7 +146,7 @@ namespace Microsoft.AspNet.DataProtection.XmlEncryption
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Encrypting to X.509 certificate with thumbprint '{0}'.", cert.Thumbprint); _logger.LogVerboseF($"Encrypting to X.509 certificate with thumbprint '{cert.Thumbprint}'.");
} }
try try
@ -157,7 +157,7 @@ namespace Microsoft.AspNet.DataProtection.XmlEncryption
{ {
if (_logger.IsErrorLevelEnabled()) if (_logger.IsErrorLevelEnabled())
{ {
_logger.LogError(ex, "An error occurred while encrypting to X.509 certificate with thumbprint '{0}'.", cert.Thumbprint); _logger.LogErrorF(ex, $"An error occurred while encrypting to X.509 certificate with thumbprint '{cert.Thumbprint}'.");
} }
throw; throw;
} }

View File

@ -68,7 +68,7 @@ namespace Microsoft.AspNet.DataProtection.XmlEncryption
// swallow all errors - it's just a log // swallow all errors - it's just a log
protectionDescriptorRule = null; protectionDescriptorRule = null;
} }
_logger.LogVerbose("Decrypting secret element using Windows DPAPI-NG with protection descriptor '{0}'.", protectionDescriptorRule); _logger.LogVerboseF($"Decrypting secret element using Windows DPAPI-NG with protection descriptor rule '{protectionDescriptorRule}'.");
} }
using (Secret secret = DpapiSecretSerializerHelper.UnprotectWithDpapiNG(protectedSecret)) using (Secret secret = DpapiSecretSerializerHelper.UnprotectWithDpapiNG(protectedSecret))

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Globalization;
using System.Security.Principal; using System.Security.Principal;
using System.Xml.Linq; using System.Xml.Linq;
using Microsoft.AspNet.Cryptography; using Microsoft.AspNet.Cryptography;
@ -11,6 +10,8 @@ using Microsoft.AspNet.DataProtection.Cng;
using Microsoft.Framework.Internal; using Microsoft.Framework.Internal;
using Microsoft.Framework.Logging; using Microsoft.Framework.Logging;
using static System.FormattableString;
namespace Microsoft.AspNet.DataProtection.XmlEncryption namespace Microsoft.AspNet.DataProtection.XmlEncryption
{ {
/// <summary> /// <summary>
@ -65,7 +66,7 @@ namespace Microsoft.AspNet.DataProtection.XmlEncryption
string protectionDescriptorRuleString = _protectionDescriptorHandle.GetProtectionDescriptorRuleString(); string protectionDescriptorRuleString = _protectionDescriptorHandle.GetProtectionDescriptorRuleString();
if (_logger.IsVerboseLevelEnabled()) if (_logger.IsVerboseLevelEnabled())
{ {
_logger.LogVerbose("Encrypting to Windows DPAPI-NG using protection descriptor '{0}'.", protectionDescriptorRuleString); _logger.LogVerboseF($"Encrypting to Windows DPAPI-NG using protection descriptor rule '{protectionDescriptorRuleString}'.");
} }
// Convert the XML element to a binary secret so that it can be run through DPAPI // Convert the XML element to a binary secret so that it can be run through DPAPI
@ -114,7 +115,7 @@ namespace Microsoft.AspNet.DataProtection.XmlEncryption
using (WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent()) using (WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent())
{ {
// use the SID to create an SDDL string // use the SID to create an SDDL string
return String.Format(CultureInfo.InvariantCulture, "SID={0}", currentIdentity.User.Value); return Invariant($"SID={currentIdentity.User.Value}");
} }
} }
} }

View File

@ -66,7 +66,7 @@ namespace Microsoft.AspNet.DataProtection.XmlEncryption
} }
else else
{ {
_logger.LogVerbose("Encrypting to Windows DPAPI for current user account ({0}).", WindowsIdentity.GetCurrent().Name); _logger.LogVerboseF($"Encrypting to Windows DPAPI for current user account ({WindowsIdentity.GetCurrent().Name}).");
} }
} }