protected bool ConnectionStringHandler() { if (this.parameters.ContainsKey(AzureConstants.ConnectionStringParamName)) { // Check to make sure that the connection string is not an empty string. // This is mainly to catch the case where someone picks up a sample // manifest and tries to deploy without specifying their connection // string first. Therefore we make this check only if the connection // string is unencrypted. string connectionString = this.parameters[AzureConstants.ConnectionStringParamName]; StorageConnection unusedRef = new StorageConnection(); if (!ConnectionStringParser.ParseConnectionString( connectionString.ToCharArray(), message => { this.traceSource.WriteError( this.logSourceId, "Section {0}, parameter {1}: {2}.", this.sectionName, AzureConstants.ConnectionStringParamName, message); }, ref unusedRef)) { return(false); } } this.connectionStringSpecified = true; return(true); }
public StorageAccountFactory(StorageConnection connection) { if (connection == null) { throw new ArgumentNullException(nameof(connection)); } this.Connection = connection; }
public CloudStorageAccountFactory(StorageConnection connection) : base(connection) { }
internal static bool ParseConnectionString(char[] connectionCharArray, Action <string> onError, ref StorageConnection storageConnection) { int charIndex = 0; bool isDsms = DsmsConnectionStringIdentifier.ToCharArray().All(c => charIndex < connectionCharArray.Length && c == connectionCharArray[charIndex++]); if (isDsms) { // Dsms return(ConnectionStringParser.ParseDsmsConnectionString(connectionCharArray, onError, ref storageConnection)); } else { // xstore return(ConnectionStringParser.ParseXStoreConnectionString(connectionCharArray, onError, ref storageConnection)); } }
private static bool ParseXStoreConnectionString(char[] connectionCharArray, Action <string> onError, ref StorageConnection storageConnection) { StorageConnection connection = new StorageConnection(); int charIndex = 0; // Remove optional xstore: prefix if (!XStoreConnectionStringIdentifier.ToCharArray().All(c => charIndex < connectionCharArray.Length && c == connectionCharArray[charIndex++])) { charIndex = 0; } char[] devStoreConnectionCharArray = AzureConstants.DevelopmentStorageConnectionString.ToCharArray(); if (connectionCharArray.Skip(charIndex).SequenceEqual(devStoreConnectionCharArray)) { connection.AccountName = DevelopmentStorageAccountName; connection.UseDevelopmentStorage = true; connection.ConnectionString = SecureStringFromCharArray( devStoreConnectionCharArray, charIndex, devStoreConnectionCharArray.Length - 1); storageConnection = connection; return(true); } // Save the connection string minus the xstore: prefix connection.ConnectionString = SecureStringFromCharArray( connectionCharArray, charIndex, connectionCharArray.Length - 1); // Parse the connection string to identify its tokens Dictionary <TokenType, string> tokenInfo = new Dictionary <TokenType, string>(); for (int j = 0; ((j < (int)TokenType.Count) && (charIndex < connectionCharArray.Length)); j++) { TokenType tokenType; try { GetTokenType(connectionCharArray, charIndex, out charIndex, out tokenType); } catch (ArgumentException ae) { onError(ae.Message); return(false); } // If both an account key and a protected account key are specified and both of them are valid, // We would be using the account key that is defined in a token closer to the end of the connection string and the other one would be ignored. if (TokenType.AccountKey == tokenType) { // Account key is handled in a special way. It is stored as a secure string // instead of a regular string. Note that it is also not converted to a // string even as an intermediate step, because strings are immutable in // .NET and there is no way to control how long the string object lives. if ((charIndex >= connectionCharArray.Length) || (connectionCharArray[charIndex] == ';')) { onError("'AccountKey' is an empty string."); return(false); } int keyStart = charIndex; for (; charIndex < connectionCharArray.Length && connectionCharArray[charIndex] != ';'; charIndex++) { ; } int afterKeyEnd = charIndex; charIndex++; // Make sure the account key has only base-64 characters try { byte[] byteArray = Convert.FromBase64CharArray( connectionCharArray, keyStart, (afterKeyEnd - keyStart)); Array.Clear(byteArray, 0, byteArray.Length); } catch (FormatException) { onError("The 'AccountKey' not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or a non-white space character among the padding characters."); return(false); } connection.AccountKey = SecureStringFromCharArray( connectionCharArray, keyStart, afterKeyEnd - 1); } else if (TokenType.ProtectedAccountKeyName == tokenType) { // Protected account key name is handled in a special way. // Instead of a direct reference to the account key in connection string, // it is a reference to a location on the machine where encrypted account key can be found. // DCA is able to decrypt it to get the account key, which would be stored as a secure string directly. // Note that this is required for Service Fabric RP managed clusters due to limitations that prevent us from using secret certs. if ((charIndex >= connectionCharArray.Length) || (connectionCharArray[charIndex] == ';')) { onError("'ProtectedAccountKeyName' is an empty string."); return(false); } int keyStart = charIndex; for (; charIndex < connectionCharArray.Length && connectionCharArray[charIndex] != ';'; charIndex++) { ; } int afterKeyEnd = charIndex; charIndex++; char[] protectedAccountKeyNameCharArray = new char[afterKeyEnd - keyStart]; Array.Copy(connectionCharArray, keyStart, protectedAccountKeyNameCharArray, 0, afterKeyEnd - keyStart); string protectedAccountKeyName = new string(protectedAccountKeyNameCharArray); char[] accountKeyCharArray; string decryptionErrorMessage; if (!ProtectedAccountKeyHelper.TryDecryptProtectedAccountKey(protectedAccountKeyName, out accountKeyCharArray, out decryptionErrorMessage)) { onError(decryptionErrorMessage); return(false); } connection.AccountKey = SecureStringFromCharArray( accountKeyCharArray, 0, accountKeyCharArray.Length - 1); Array.Clear(accountKeyCharArray, 0, accountKeyCharArray.Length); } else { StringBuilder tokenInfoBuilder = new StringBuilder(); while (charIndex < connectionCharArray.Length && connectionCharArray[charIndex] != ';') { tokenInfoBuilder.Append(connectionCharArray[charIndex++]); } charIndex++; tokenInfo[tokenType] = tokenInfoBuilder.ToString(); } } // Get DefaultEndpointsProtocol if (tokenInfo.ContainsKey(TokenType.DefaultEndpointsProtocol)) { string protocol = tokenInfo[TokenType.DefaultEndpointsProtocol]; if (!protocol.Equals(Http, StringComparison.OrdinalIgnoreCase) && !protocol.Equals(Https, StringComparison.OrdinalIgnoreCase)) { onError( string.Format( "The DefaultEndpointsProtocol specificed in the connection string is invalid. Valid values are {0} and {1}", Http, Https)); return(false); } connection.IsHttps = protocol.Equals(Https, StringComparison.OrdinalIgnoreCase); } else { connection.IsHttps = true; } // Get AccountName if (!tokenInfo.ContainsKey(TokenType.AccountName)) { onError("The Connection string does not contain 'AccountName'."); return(false); } connection.AccountName = tokenInfo[TokenType.AccountName]; // Get AccountKey if (null == connection.AccountKey) { onError("The Connection string does not contain 'AccountKey'."); return(false); } string endpointTokenName = string.Empty; try { // Get endpoints foreach (var tokenType in new[] { TokenType.BlobEndpoint, TokenType.QueueEndpoint, TokenType.TableEndpoint, TokenType.FileEndpoint }) { if (tokenInfo.ContainsKey(tokenType)) { endpointTokenName = TokenPrefixes[tokenType]; if (tokenType == TokenType.BlobEndpoint) { connection.BlobEndpoint = new Uri(tokenInfo[tokenType]); } else if (tokenType == TokenType.QueueEndpoint) { connection.QueueEndpoint = new Uri(tokenInfo[tokenType]); } else if (tokenType == TokenType.TableEndpoint) { connection.TableEndpoint = new Uri(tokenInfo[tokenType]); } else if (tokenType == TokenType.FileEndpoint) { connection.FileEndpoint = new Uri(tokenInfo[tokenType]); } } } storageConnection = connection; } catch (UriFormatException e) { onError( string.Format( "The value specified for endpoint '{0}' in connection string is not in the correct format. Exception: {1}", endpointTokenName, e)); return(false); } return(true); }
// The expected format of connectionString is "dsms:SourceLocation=blahblabla;EndpointSuffix=blahblah;AutoPilotServiceName=bla" // Where dsms: SourceLocation= and EndpointSuffix= are required and case sensitive, and AutoPilotServiceName is optional private static bool ParseDsmsConnectionString(char[] connectionCharArray, Action <string> onError, ref StorageConnection storageConnection) { int charIndex = 0; // consuming dsms: from connectionstring DsmsConnectionStringIdentifier.ToCharArray().All(c => charIndex < connectionCharArray.Length && c == connectionCharArray[charIndex++]); // Parse the connection string to identify its tokens Dictionary <DsmsTokenType, string> tokenInfo = new Dictionary <DsmsTokenType, string>(); for (int j = 0; ((j < (int)DsmsTokenType.Count) && (charIndex < connectionCharArray.Length)); j++) { // Look for SourceLocation, EndpointPrefix or AutopilotServiceName DsmsTokenType tokenType; try { GetDsmsTokenType(connectionCharArray, charIndex, out charIndex, out tokenType); // reached the end of the connection string // this is needed for optional parameters if (tokenType == DsmsTokenType.Empty) { break; } } catch (ArgumentException ae) { onError(ae.Message); return(false); } // Reading content of specified prefix StringBuilder tokenInfoBuilder = new StringBuilder(); while (charIndex < connectionCharArray.Length && connectionCharArray[charIndex] != ';') { tokenInfoBuilder.Append(connectionCharArray[charIndex++]); } // consuming ';' charIndex++; // Dsms expects one and only one of each prefix (SourceLocation, EndpointSuffix) try { tokenInfo.Add(tokenType, tokenInfoBuilder.ToString()); } catch (Exception e) { onError($"Invalid Dsms connectionString. Exception {e}"); return(false); } } try { string sourceLocation = tokenInfo.ContainsKey(DsmsTokenType.SourceLocation)? tokenInfo[DsmsTokenType.SourceLocation] : null; string endpointSuffix = tokenInfo.ContainsKey(DsmsTokenType.EndpointSuffix)? tokenInfo[DsmsTokenType.EndpointSuffix] : null; string autoPilotServiceName = tokenInfo.ContainsKey(DsmsTokenType.AutopilotServiceName) ? tokenInfo[DsmsTokenType.AutopilotServiceName] : null; storageConnection = new StorageConnection( sourceLocation, endpointSuffix, autoPilotServiceName); } catch (Exception e) { onError($"Invalid Dsms connectionString. Empty parameter. Exception {e}"); return(false); } return(true); }