Forum Discussion

Roflcopter's avatar
Roflcopter
Icon for Nimbostratus rankNimbostratus
Feb 12, 2018

Content-Security-Policy

I am trying to construct and iRule that will put a variable into a HTTP Header.

The requirements are -

  1. When a client connects set their HTTP:host as a variable for later use
  2. Check that the HTTP:host matches from a list defined in a datagroup
  3. If it does match then response to the client with "X-Content-Security-Policy" "frame-ancestors 'self' '$host'" and "X-Content-Security-Policy" "frame-scr 'self' '$host'"
  4. If there is no match then respond with HTTP::header insert "X-Content-Security-Policy" "frame-ancestors 'self'" and "HTTP::header insert "X-Content-Security-Policy" "frame-scr 'self'"

I am having trouble piecing it all together into a single rule, I can get by with basic coding but I am pretty limited when it comes to putting multiple steps together like the above.

So far I have the below which isn't going to work, can someone here provide some assistance?

When HTTP_REQUEST { 

Set host [HTTP::host]

if { [class match [HTTP::header "Host"] contains host_lookup_table] } {

 log.local0 URI=$host

When HTTP_RESPONSE {

if {![HTTP::header exists "Content-Security-Policy"] } {
       HTTP::header insert "Content-Security-Policy" "frame-ancestors 'self' $host"
       HTTP::header insert "Content-Security-Policy" "frame-scr 'self' '$host'"
           }

if {![HTTP::header exists "X-Content-Security-Policy"] } {
       HTTP::header insert "X-Content-Security-Policy" "frame-ancestors 'self' '$host'"
       HTTP::header insert "X-Content-Security-Policy" "frame-scr 'self' '$host'"
    }

}

else 

When HTTP_RESPONSE {

if {![HTTP::header exists "Content-Security-Policy"] } {
       HTTP::header insert "Content-Security-Policy" "frame-ancestors 'self'"
       HTTP::header insert "Content-Security-Policy" "frame-scr 'self'"
           }

if {![HTTP::header exists "X-Content-Security-Policy"] } {
       HTTP::header insert "X-Content-Security-Policy" "frame-ancestors 'self'"
       HTTP::header insert "X-Content-Security-Policy" "frame-scr 'self'"
    }
}

10 Replies

  • Hi,

     

    The code stated below may work. Can you try it?

     

        when CLIENT_ACCEPTED {
            set host_exist 0
        }   
    
        when HTTP_REQUEST {
           set host [HTTP::host]
           if { [class match $host contains host_lookup_table] } {
              set host_exist 1        
           }
        } 
    
        when HTTP_RESPONSE {
           if { $host_exist equals 1 } {
               HTTP::header insert "X-Content-Security-Policy" "frame-ancestors 'self' $host"
               HTTP::header insert "X-Content-Security-Policy" "frame-scr 'self' '$host'"
           }
           else {
               HTTP::header insert "X-Content-Security-Policy" "frame-ancestors 'self'"
               HTTP::header insert "X-Content-Security-Policy" "frame-scr 'self'"
           }
        }
    • Roflcopter's avatar
      Roflcopter
      Icon for Nimbostratus rankNimbostratus

      Thanks a lot. Looks like it would work, I like the way you used a second variable that can be used when making the decision on what to send back to the client, so nice and simple!

       

      I'll give it a test run tomorrow, thanks for taking the time to post a response!

       

    • oguzy_191375's avatar
      oguzy_191375
      Icon for Nimbostratus rankNimbostratus

      You are welcome. I hope it can solve your issue. After your test run tomorrow, if it works, would you mind accepting the answer?

       

    • Roflcopter's avatar
      Roflcopter
      Icon for Nimbostratus rankNimbostratus

      Had to add a bit more functionality to the rule. Turned out that the site actually had other sites framed within it so this mean that the original host captured wasn't enough. We also had to return the framed site.

      So using a datagroup we could make a key pair using a string and a value, for example host1.com = host2.com.

      Then in the irule we capture the HTTP:host in the HTTP_REQUEST, set it as the variable $host, then look that variable up in the datagroup and return its value as the variable $value.

      Then $value can be used in the HTTP_RESPONSE

      when HTTP_REQUEST {
              set host [HTTP::host]
      
              if { [class match $host contains content-security] } {
                    set host_exist 1    
                    set value [class match -value "$host" equals "content-security"]
              }
          } 
      
          when HTTP_RESPONSE {
              if { $host_exist equals 1 } {
                     HTTP::header insert "Content-Security-Policy" "frame-ancestors 'self' $value"
                     HTTP::header insert "X-Content-Security-Policy" "frame-scr 'self' '$value'"
              }
              else {
                     HTTP::header insert "Content-Security-Policy" "frame-ancestors 'self'"
                     HTTP::header insert "X-Content-Security-Policy" "frame-scr 'self'"
              }
          }
      
  • oguzy's avatar
    oguzy
    Icon for Cirrostratus rankCirrostratus

    Hi,

     

    The code stated below may work. Can you try it?

     

        when CLIENT_ACCEPTED {
            set host_exist 0
        }   
    
        when HTTP_REQUEST {
           set host [HTTP::host]
           if { [class match $host contains host_lookup_table] } {
              set host_exist 1        
           }
        } 
    
        when HTTP_RESPONSE {
           if { $host_exist equals 1 } {
               HTTP::header insert "X-Content-Security-Policy" "frame-ancestors 'self' $host"
               HTTP::header insert "X-Content-Security-Policy" "frame-scr 'self' '$host'"
           }
           else {
               HTTP::header insert "X-Content-Security-Policy" "frame-ancestors 'self'"
               HTTP::header insert "X-Content-Security-Policy" "frame-scr 'self'"
           }
        }
    • Roflcopter's avatar
      Roflcopter
      Icon for Nimbostratus rankNimbostratus

      Thanks a lot. Looks like it would work, I like the way you used a second variable that can be used when making the decision on what to send back to the client, so nice and simple!

       

      I'll give it a test run tomorrow, thanks for taking the time to post a response!

       

    • oguzy's avatar
      oguzy
      Icon for Cirrostratus rankCirrostratus

      You are welcome. I hope it can solve your issue. After your test run tomorrow, if it works, would you mind accepting the answer?

       

    • Roflcopter's avatar
      Roflcopter
      Icon for Nimbostratus rankNimbostratus

      Had to add a bit more functionality to the rule. Turned out that the site actually had other sites framed within it so this mean that the original host captured wasn't enough. We also had to return the framed site.

      So using a datagroup we could make a key pair using a string and a value, for example host1.com = host2.com.

      Then in the irule we capture the HTTP:host in the HTTP_REQUEST, set it as the variable $host, then look that variable up in the datagroup and return its value as the variable $value.

      Then $value can be used in the HTTP_RESPONSE

      when HTTP_REQUEST {
              set host [HTTP::host]
      
              if { [class match $host contains content-security] } {
                    set host_exist 1    
                    set value [class match -value "$host" equals "content-security"]
              }
          } 
      
          when HTTP_RESPONSE {
              if { $host_exist equals 1 } {
                     HTTP::header insert "Content-Security-Policy" "frame-ancestors 'self' $value"
                     HTTP::header insert "X-Content-Security-Policy" "frame-scr 'self' '$value'"
              }
              else {
                     HTTP::header insert "Content-Security-Policy" "frame-ancestors 'self'"
                     HTTP::header insert "X-Content-Security-Policy" "frame-scr 'self'"
              }
          }