DCSIMG
March 2012 - Posts - Manu Cohen-Yashar's Blog

Manu Cohen-Yashar's Blog

March 2012 - Posts

Application security auditing and logging

Auditing is one of the main pillars of security policies. The question is how to do it wisely

The infrastructure can log almost everything. For example access to files, registry keys databases etc. The problem is that the infrastructure has no knowledge about the application use cases. It means that the context for these logs is missing.

Let us ask what is the purpose of auditing? The trivial reason is to collect information that will be useful in case of a problem, yet how do you know that there is a problem after all?

Auditing can help you identify that you are in an abnormal state and something is wrong.
To do that you have to be able to distinguish between normality and abnormality. The application knows its use cases. It knows their behavior patterns and so can identify that something is wrong. This is why only the application layer can perform smart security auditing.

Application logging and auditing is used to collect enough information to analyze the behavior of the application use cases and identify any abnormal situation, then the information collected with traditional logging is used to identify the problem and find the best action.

Enjoy

Manu

Http error 405 when calling STS

I wrote a simple example for demonstrating delegation with Windows Identity Framework (WIF).
I created a simple web site that used a simple custom STS for authentication. The web site called another web service to calculate a simple calculation (calculator).

The web site used passive federation using a simple asp.net STS. SOAP Web service in general can only use passive federation for authentication, so I created another WCF custom STS.

The idea was that the web application will obtain an act-as token from the active STS using the token it received from the client (using the passive STS) and then call the calculator web service.

When I run the code I got the "http error 405 method not allowed".

Http error 405 means that there is a mismatch between the http verb (e.g. Post, Get) between the call and the service. If the service waits for a http put and we send a http get request this is the error that will be triggered.

My problem was simple. I called the base address of the STS instead of the STS itself. I did that by specifying the base address of the STS in the issuer configuration. When I fixed the address to the real address of the STS the problem was solved.

 <customBinding>
   <binding name="CustomBinding_ICalc">
     <security authenticationMode="IssuedTokenForCertificate" 
messageSecurityVersion="WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10"> <issuedTokenParameters keyType="SymmetricKey" tokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"> <issuer address="http://manu-newlap/WCFSTS/service.svc" binding="ws2007HttpBinding" bindingConfiguration="http://manu-newlap/WCFSTS"> </issuer> <issuerMetadata address="http://manu-newlap/WCFSTS/mex" /> </issuedTokenParameters> </security> <httpTransport/> </binding> </customBinding>

The call to the STS to obtain an Act-As token is implemented by sending a http post request that contains the bootstrap token received from the passive STS. The base address does not allow non Get requests so my Post request was rejected.

remember that STS is a simple WCF service. The same rules that applies in simple WCF applies here.

Hope this will help.

Manu

כלכלת ענן

Hi this post will be written in Hebrew (sorry for all English speakers)

כולנו שומעים על ענן מכל כיוון אפשרי. נשאלת השאלה למה?
מה עושה את הענן הזה לשם החם הבא? מה הסוד מאחורי המושג הזה?

הכול מתחיל ונגמר בכסף. הסיפור הוא כלכלי.

מחוק מור למדנו שכל שנתיים מערכות מכפילות את יכולתן הטכנולוגית השאלה שנשאלת מה קורה למחיר? בסביבה הטכנולוגית כיום הלקוח התרגל לא רק לקבל מערכות טובות יותר ככל שהזמן עובר, אלא גם לשלם פחות. זה מוזר מבחינה כלכלית – לקבל יותר אך לשלם פחות.

הכול טוב ויפה מצדו של הצרכן אבל נותן השירות או ספק התוכנה נמצא במצב מביך, הלקוח דורש דרישות הולכות וגדלות אך מצד שני הוא מוכן לשלם פחות. בימינו הצרכן דורש אמינות מושלמת זמינות מוחלטת, ביזור ועמידה בעומסים משתנים. ניתן כמובן לספק יכולות כאלו הבעיה רק שזה ממש יקר. והלקוח כאמור לא מוכן לשלם.

במצב כזה אין ברירה אלא לשנות משהו בסיסי כי במצב הנוכחי פשוט אי אפשר לספק את הדרישות במחירי השוק. פה מגיע הענן.

הענן הוא ההזדמנות של השוק לגדול מבחינה טכנולוגית ועדיין להישאר רלוונטי מבחינה כלכלית. זוהי הסיבה שכולם מדברים על הענן מפני שזו היא התשתית עליה תתבסס התעשייה בעתיד הקרוב.

הרעיון שעומד מאחורי הענן אינו חדש. תשתיות הן דבר יקר ובעל נצילות נמוכה. שיתוף תשתיות הוא פוטנציאל אדיר לחיסכון בכסף. המימוש המפורסם ביותר של הרעיון הזה מגיע מתשתיות החשמל. למי מאתנו יש תחנת כוח ביתית שמספקת את כל תצרוכת החשמל שלנו? לרובנו זו נראית שאלה מגוחכת. למה לי לבנות תשתית יקרה של גנרטורים שיספקו לי הרבה חשמל למזגנים בקיץ ולחימום בחורף ומעט חשמל באביב ובסתיו כשאני יכול בפשטות כה רבה לקנות חשמל בזול מחברת חשמל ולשלם בדיוק לפי הצריכה שלי?

האנלוגיה ברורה. למה לי להקים מרכז מחשוב יקר שיספק לי את הכוח הדרוש לשעות העומס ויעמוד בטל בשאר ימות השנה כשאני יכול בפשטות לקנות כוח מחשוב ואזורי אחסון בענן ולשלם בדיוק לפי צריכה?

כנראה עוד מספר שנים השאלה עם לעבוד בענן תראה טריוויאלית בדיוק כמו השאלה אם לרכוש חשמל מספק מרכזי. כיום אנו בתחילתו של עידן אבל הכיוון ברור והתעשייה כולה מתנהגת בהתאם. ספקי התקשורת (Telecoms) בונים לנו ערוצים ייעודיים לענן כדי להבטיח ביצועים בסביבה מבוזרת. ספקי הענן בונים מרכזי מחשוב (Data Centers) ענקיים ומשקיעים מיליארדים בפיתוח הטכנולוגיה אשר תאפשר לנו בקלות להשתמש בשירותי הענן שלהם. יצרני מערכות ההפעלה וה – Hypervisors בונים תשתיות תוכנה ייעודיות לבניית מרכזי מחשוב ענן (ראה Windows Server 8 כדוגמא). יצרני החומרה בונים רכיבים מיוחדים עבור שרתים בענן וספקי התוכנה מספקים את מרכולתם כ – Software as a Service.

בקיצור הענן הוא הדבר הבא כי הוא מספק את ההזדמנות הכלכלית שכל כך דרושה לתעשיית המידע.

Azure ServiceBus Topic using REST API – Part 4

In the three last post's we learned how to use Azure ServiceBus REST API to send and receive messages using Topics.

The difference between Queues and Topics is the fact that with topics different customers can receive different messages according message filtering which is deployed as filtering rules on the subscription. MSDN describe the following about topics and rules:

image

Topics extend the messaging features provided by Queues with the addition of Publish-Subscribe capabilities.
Each Subscription can define one or multiple Rule entities. Each Rule specifies a filter expression that is used to filter messages that pass through the subscription and a filter action that can modify message properties. In particular, the SqlFilterExpression class allows you to define a SQL92-like condition on message properties:

  • OrderTotal > 5000 OR ClientPriority > 2
  • ShipDestinationCountry = ‘USA’ AND ShipDestinationState = ‘WA’

Conversely, the SqlFilterAction class can be used to modify, add or remove properties, as the filter expression is true and the message selected, using a syntax similar to that used by the SET clause of an UPDATE SQL-command.

  • SET AuditRequired = 1
  • SET Priority = 'High', Severity = 1

Each matching rule generates a separate copy of the published message, so any subscription can potentially generate more copies of the same message, one for each matching rule.

Let us learn how to Add a rule and action using the REST API.

To add a rule to a subscription we need to provide a rule description. To do that I created a rule, action and filter description classes.

Rule Description
  1. /// <summary>
  2. /// Helper class to serialize a rule for a subscription
  3. /// </summary>
  4. [DataContract(Name = "RuleDescription", Namespace = "http://schemas.microsoft.com/netservices/2010/10/servicebus/connect")]
  5. public sealed class RuleDescription
  6. {
  7.     /// <summary>
  8.     /// The default name used in creating default rule when adding subscriptions
  9.     /// to a topic. The name is "$Default".
  10.     /// </summary>
  11.     public const string DefaultRuleName = "$Default";
  12.     public RuleDescription()
  13.         : this(new TrueFilter())
  14.     {
  15.     }
  16.     public RuleDescription(Filter filter)
  17.     {
  18.         if (filter == null)
  19.         {
  20.             throw new ArgumentNullException("filter");
  21.         }
  22.         this.Filter = filter;
  23.     }
  24.     [DataMember(Name = "Filter", IsRequired = false, Order = 1001, EmitDefaultValue = false)]
  25.     public Filter Filter { get; set; }
  26.     [DataMember(Name = "Action", IsRequired = false, Order = 1002, EmitDefaultValue = false)]
  27.     public RuleAction Action { get; set; }
  28.     public string TopicPath { getset; }
  29.     public string SubscriptionName { get; set; }
  30.     public string Name { getset; }       
  31.    
  32. }

The rule description contains rule actions.

Rule actions
  1. /// <summary>
  2. /// Helper class to serialize a rule for a subscription
  3. /// </summary>
  4. [DataContract(Name = "RuleAction", Namespace = "http://schemas.microsoft.com/netservices/2010/10/servicebus/connect")]
  5. [KnownType(typeof(EmptyRuleAction))]
  6. [KnownType(typeof(SqlRuleAction))]
  7. public abstract class RuleAction
  8. {
  9.     internal RuleAction()
  10.     {
  11.     }
  12. }
  13. /// <summary>
  14. /// Helper class to serialize a rule for a subscription
  15. /// </summary>
  16. [DataContract(Name = "EmptyRuleAction", Namespace = "http://schemas.microsoft.com/netservices/2010/10/servicebus/connect")]
  17. public sealed class EmptyRuleAction : RuleAction
  18. {
  19. }
  20. /// <summary>
  21. /// Helper class to serialize a rule for a subscription
  22. /// </summary>
  23. [DataContract(Name = "SqlRuleAction", Namespace = "http://schemas.microsoft.com/netservices/2010/10/servicebus/connect")]
  24. public sealed class SqlRuleAction : RuleAction
  25. {
  26.     public const int DefaultCompatibilityLevel = 20;
  27.     public SqlRuleAction(string sqlExpression)
  28.     {
  29.         if (string.IsNullOrEmpty(sqlBLOCKED EXPRESSION
  30.         {
  31.             throw new ArgumentNullException("sqlExpression");
  32.         }
  33.         this.SqlExpression = sqlExpression;
  34.         this.CompatibilityLevel = DefaultCompatibilityLevel;
  35.     }
  36.     [DataMember(Order = 0x10001)]
  37.     public string SqlExpression { get; private set; }
  38.     [DataMember(Order = 0x10002)]
  39.     public int CompatibilityLevel { get; private set; }
  40. }

The rule description contains rule filters

Rule Filters
  1. /// <summary>
  2. /// Helper class to serialize a rule for a subscription
  3. /// </summary>
  4. [DataContract(Name = "Filter", Namespace = "http://schemas.microsoft.com/netservices/2010/10/servicebus/connect")]
  5. [KnownType(typeof(SqlFilter))]
  6. [KnownType(typeof(TrueFilter))]
  7. [KnownType(typeof(FalseFilter))]
  8. [KnownType(typeof(CorrelationFilter))]
  9. public abstract class Filter
  10. {
  11.     internal Filter()
  12.     {
  13.     }
  14. }
  15. /// <summary>
  16. /// Helper class to serialize a rule for a subscription
  17. /// </summary>
  18. [DataContract(Name = "SqlFilter", Namespace = "http://schemas.microsoft.com/netservices/2010/10/servicebus/connect")]
  19. [KnownType(typeof(TrueFilter))]
  20. [KnownType(typeof(FalseFilter))]
  21. public class SqlFilter : Filter
  22. {
  23.     public const int DefaultCompatibilityLevel = 20;
  24.     public SqlFilter(string sqlExpression)
  25.     {
  26.         if (String.IsNullOrEmpty(sqlBLOCKED EXPRESSION
  27.         {
  28.             throw new ArgumentNullException("sqlExpression");
  29.         }
  30.         this.SqlExpression = sqlExpression;
  31.         this.CompatibilityLevel = DefaultCompatibilityLevel;
  32.     }
  33.     [DataMember(Order = 0x10001)]
  34.     public string SqlExpression { get; set; }
  35.     [DataMember(Order = 0x10002)]
  36.     public int CompatibilityLevel { get; set; }
  37. }
  38. /// <summary>
  39. /// Helper class to serialize a rule for a subscription
  40. /// </summary>
  41. [DataContract(Name = "TrueFilter", Namespace = "http://schemas.microsoft.com/netservices/2010/10/servicebus/connect")]
  42. public sealed class TrueFilter : SqlFilter
  43. {
  44.     public TrueFilter()
  45.         : base("1=1")
  46.     {
  47.     }
  48. }
  49. /// <summary>
  50. /// Helper class to serialize a rule for a subscription
  51. /// </summary>
  52. [DataContract(Name = "FalseFilter", Namespace = "http://schemas.microsoft.com/netservices/2010/10/servicebus/connect")]
  53. public sealed class FalseFilter : SqlFilter
  54. {
  55.     public FalseFilter()
  56.         : base("1=0")
  57.     {
  58.     }
  59. }
  60. /// <summary>
  61. /// Helper class to serialize a rule for a subscription
  62. /// </summary>
  63. [DataContract(Name = "CorrelationFilter", Namespace = "http://schemas.microsoft.com/netservices/2010/10/servicebus/connect")]
  64. public sealed class CorrelationFilter : Filter
  65. {
  66.     public CorrelationFilter(string correlationId)
  67.     {
  68.         this.CorrelationId = correlationId;
  69.     }
  70.     [DataMember(Order = 0x10001)]
  71.     public string CorrelationId { get; private set; }
  72. }

Now we are ready to add a new rule using REST API

Add a Rule
  1. public static void CreateRule(string serviceNamespace, string topicName, string subscriptionName, RuleDescription description , string token)
  2. {            
  3.     var ruleAddress = string.Format("https://{0}.servicebus.windows.net/{1}/subscriptions/{2}/rules/{3}", serviceNamespace, topicName, subscriptionName, description.Name);
  4.     try
  5.     {
  6.         var defautRuleAddress = string.Format("https://{0}.servicebus.windows.net/{1}/subscriptions/{2}/rules/$Default", serviceNamespace, topicName, subscriptionName);
  7.         DeleteResource(defautRuleAddress, token);
  8.     }
  9.     catch (WebException ex)
  10.     {
  11.         //The default rule was already deleted
  12.         if (ex.Message != "The remote server returned an error: (404) Not Found.")
  13.             throw;
  14.     }                       
  15.     WebClient webClient = new WebClient();
  16.     webClient.Headers[HttpRequestHeader.Authorization] = token;
  17.     webClient.Headers[HttpRequestHeader.ContentType] = @"application/atom+xml;type=entry;charset=utf-8";
  18.     var ruleDescription = Encoding.UTF8.GetString(Serialize<RuleDescription>(description));
  19.     var putData = @"<entry xmlns='http://www.w3.org/2005/Atom'><content type='application/xml'>" + ruleDescription  + @"</content></entry>";
  20.     webClient.UploadData(ruleAddress, "PUT", Encoding.UTF8.GetBytes(putData));
  21. }

As you can see the first thing we do is delete the default rule that accepts all messages. Then we attach the serialization of our rule description to a PUT Http request we send to the URI of the new rule at:
https://{serviceNamespace}.servicebus.windows.net/{topicName}/subscriptions/{subscriptionName}/rules/{ruleName}

That is it. We have a new rule on our subscription.

With that I end the Series of post about using REST API of AppFabric Topics.

Enjoy

Manu

Azure ServiceBus Topic using REST API – Part 3

In the last two posts we showed how to use the Azure ServiceBus service bus REST API to send a message to a topic.
In this post we will see how to listen on a topic and receive a message.

There are two options:

1. Receive a message and delete it from the topic.

Receive and Delete
  1. public static T ReceiveAndDeleteMessage<T>(string serviceNamespace, string topicName,
  2.     string subscriptionName, string token) where T : class
  3. {
  4.     var address = string.Format("https://{0}.{1}/{2}/subscriptions/{3}/messages/head?timeout=10",
  5.         serviceNamespace, sbHostName, topicName, subscriptionName);
  6.     WebClient webClient = new WebClient();
  7.     webClient.Headers[HttpRequestHeader.Authorization] = token;
  8.     byte[] response = webClient.UploadData(address, "DELETE", new byte[0]);
  9.     return Deserialize<T>(response);            
  10. }

2. Receive the message but keep it locked on the queue until we decide to delete it (for example after message processing succeeded).

Receive and Peek
  1. public static T ReceiveAndPeekMessage<T>(string serviceNamespace, string topicName,
  2.     string subscriptionName, string token) where T : class
  3. {
  4.     var address = string.Format("https://{0}.{1}/{2}/subscriptions/{3}/messages/head?timeout=10",
  5.         serviceNamespace, sbHostName, topicName, subscriptionName);
  6.     WebClient webClient = new WebClient();
  7.     webClient.Headers[HttpRequestHeader.Authorization] = token;
  8.     byte[] response = (webClient.UploadData(address, "POST", new byte[0]));
  9.     //use the information in the BrokerProperties to unlock the message
  10.     var serilaizedBrokeredProperties = webClient.ResponseHeaders["BrokerProperties"];
  11.     BrokerProperties brokerProperties = BrokerProperties.Deserialize(serilaizedBrokeredProperties);            
  12.    
  13.     return Deserialize<T>(response);
  14. }

The following table describe the information that will be placed in the brokerProperties object 

Response Header

Description

BrokerProperties{MessageLocation}

The URI of the locked message. This URI is needed to unlock or delete the message.

BrokerProperties{LockTocken}

The lock ID for the locked message. This ID is needed to delete the locked message.

BrokerProperties{LockLocation}

The lock URI for the locked message. This URI is needed to unlock the message for processing by other receivers. The lock URI will be the following format: https://{serviceNamespace}.appfabric.Windows.net/{topic-path}/subscriptions/{subscription-name}/messages/{message-id}/{lock-id}.

To delete a lock or delete message (after the lock is deleted) I will use a general method for deleting service bus resources

Delete Resources
  1. private static void DeleteResource(string address, string token)
  2. {
  3.     WebClient webClient = new WebClient();
  4.     webClient.Headers[HttpRequestHeader.Authorization] = token;
  5.     webClient.UploadData(address, "DELETE", new byte[0]);
  6. }

That's all we received a message. On the next post we will learn how to create a rule for a subscription.

Enjoy

manu

Azure ServiceBus Topic using REST API – Part 2

In the last post I described why to use REST API when working with Azure service bus and demonstrated how to create a topic and subscription.

In this post we will actually send a message to the topic.

When sending a http request with a message to a topic we have to provide two special headers
1. Authorization header with the token we received from ACS
2.  BrokerProperties with Json serialization of metadata of metadata about our message.

To do that let us create a special class that will help us represent and serialize the metadata.

Broker Properties
  1. /// <summary>
  2. /// Container for general properties of messages that are placed in the "BrokerProperties" http header and can be used to filter messages
  3. /// </summary>
  4. [DataContract]
  5. public sealed class BrokerProperties
  6. {
  7.     private static readonly DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(BrokerProperties));
  8.     [DataMember(EmitDefaultValue = false)]
  9.     public string CorrelationId { get; set; }
  10.     [DataMember(EmitDefaultValue = false)]
  11.     public string SessionId { get; set; }
  12.     [DataMember(EmitDefaultValue = false)]
  13.     public int? DeliveryCount { get; set; }
  14.     [DataMember(EmitDefaultValue = false)]
  15.     public Guid? LockToken { get; set; }
  16.     [DataMember(EmitDefaultValue = false)]
  17.     public string MessageId { get; set; }
  18.     [DataMember(EmitDefaultValue = false)]
  19.     public string Label { get; set; }
  20.     [DataMember(EmitDefaultValue = false)]
  21.     public string ReplyTo { get; set; }
  22.     [DataMember(EmitDefaultValue = false)]
  23.     public long? SequenceNumber { get; set; }
  24.     [DataMember(EmitDefaultValue = false)]
  25.     public string To { get; set; }
  26.     public DateTime? LockedUntilUtc { get; set; }
  27.     public DateTime? ScheduledEnqueueTimeUtc { get; set; }
  28.     public TimeSpan? TimeToLive { get; set; }
  29.     [DataMember(EmitDefaultValue = false)]
  30.     public string ReplyToSessionId { get; set; }
  31.     [DataMember(Name = "LockedUntilUtc", EmitDefaultValue = false)]
  32.     public string LockedUntilUtcString
  33.     {
  34.         get
  35.         {
  36.             if (this.LockedUntilUtc != null && this.LockedUntilUtc.HasValue)
  37.             {
  38.                 return this.LockedUntilUtc.Value.ToString("r");
  39.             }
  40.             return null;
  41.         }
  42.         set
  43.         {
  44.             try
  45.             {
  46.                 // When deserializing from JSON format, attempt to parse the value.
  47.                 // If the value cannot be parsed as a date time, ignore it.
  48.                 this.LockedUntilUtc = DateTime.Parse(value, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
  49.             }
  50.             catch
  51.             {
  52.             }
  53.         }
  54.     }
  55.     [DataMember(Name = "ScheduledEnqueueTimeUtc", EmitDefaultValue = false)]
  56.     public string ScheduledEnqueueTimeUtcString
  57.     {
  58.         get
  59.         {
  60.             if (this.ScheduledEnqueueTimeUtc != null && this.ScheduledEnqueueTimeUtc.HasValue)
  61.             {
  62.                 return this.ScheduledEnqueueTimeUtc.Value.ToString("r");
  63.             }
  64.             return null;
  65.         }
  66.         set
  67.         {
  68.             try
  69.             {
  70.                 // When deserializing from JSON format, attempt to parse the value.
  71.                 // If the value cannot be parsed as a date time, ignore it.
  72.                 this.ScheduledEnqueueTimeUtc = DateTime.Parse(value, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
  73.             }
  74.             catch
  75.             {
  76.             }
  77.         }
  78.     }
  79.     [DataMember(Name = "TimeToLive", EmitDefaultValue = false)]
  80.     public double TimeToLiveString
  81.     {
  82.         get
  83.         {
  84.             if (this.TimeToLive != null && this.TimeToLive.HasValue)
  85.             {
  86.                 return this.TimeToLive.Value.TotalSeconds;
  87.             }
  88.             return 0;
  89.         }
  90.         set
  91.         {
  92.             // This is needed as TimeSpan.FromSeconds(TimeSpan.MaxValue.TotalSeconds) throws Overflow exception.
  93.             if (TimeSpan.MaxValue.TotalSeconds == value)
  94.             {
  95.                 this.TimeToLive = TimeSpan.MaxValue;
  96.             }
  97.             else
  98.             {
  99.                 this.TimeToLive = TimeSpan.FromSeconds(value);
  100.             }
  101.         }
  102.     }
  103.     public static BrokerProperties Deserialize(string jsonString)
  104.     {
  105.         using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
  106.         {
  107.             return (BrokerProperties)serializer.ReadObject(ms);
  108.         }
  109.     }
  110.     public string Serialize()
  111.     {
  112.         using (MemoryStream memoryStream = new MemoryStream())
  113.         {
  114.             serializer.WriteObject(memoryStream, this);
  115.             memoryStream.Position = 0;
  116.             using (StreamReader reader = new StreamReader(memoryStream))
  117.             {
  118.                 return reader.ReadToEnd();
  119.             }
  120.         }
  121.     }
  122. }

Now we know how to create a token (previous post) and represent metadata. so let us send a message

Code Snippet
  1. public static void SendMessage<T>(string serviceNamespace, string topicName,
  2.     T content, string token, string receiverName) where T : class
  3. {
  4.     var fullAddress = string.Format("https://{0}.{1}/{2}//messages?timeout=60",
  5.         serviceNamespace, sbHostName, topicName);
  6.     BrokerProperties brokeredProparties = new BrokerProperties();
  7.     brokeredProparties.To = receiverName;
  8.     WebClient webClient = new WebClient();
  9.     webClient.Headers[HttpRequestHeader.Authorization] = token;            
  10.     webClient.Headers["BrokerProperties"] = brokeredProparties.Serialize();
  11.                 
  12.     //All the message's properties are propagated so they can be used in a Sql Filter
  13.     foreach (var prop in typeof(T).GetProperties())
  14.     {
  15.         webClient.Headers[prop.Name] = prop.GetValue(content, null).ToString();
  16.     }            
  17.     webClient.UploadData(fullAddress, "POST", Serialize(content));
  18. }

As you can see I put the receiver name in the "To" properties of the BrokerProperties object. This will allow us later to create a rule that filter the messages accordingly (e.g. To=receiver)

Also you can see that I propagated all of the message's properties. A propagated property is placed as a Http header and provide the ability to later filter messages according to its value by creating a relevant rule.
In production I assume that you will propagate only the properties you need !!!

The body message contains the DataContract Serialization of our data.
All we need to do is send the Http Request (using POST verb) to our topic at:
https://{namespace}.{appfabric.windows.net}/{topicname}//messages?timeout=60

Serialization
  1. private static byte[] Serialize<T>(T content) where T : class
  2. {
  3.     try
  4.     {
  5.         var serializer = new DataContractSerializer(typeof(T));
  6.         MemoryStream memstream = new MemoryStream();
  7.         var writer = XmlDictionaryWriter.CreateTextWriter(memstream, Encoding.UTF8);
  8.         serializer.WriteObject(writer, content);
  9.         writer.Flush();
  10.         return memstream.ToArray();
  11.     }
  12.     catch (Exception)
  13.     {
  14.         // log this
  15.         return null;
  16.     }           
  17. }


Enjoy

Manu