基本的に前回とほぼ同一ですが、SQL Azure のファイアウォール制御(作成・列挙・削除)もアクティビティ化してみました。ファイアウォール制御 API 自体は特に難しいものでもなく、非常に簡単な形式となっています。メッセージ生成が必要なのも新規作成の際のみです。
前回同様ベースとなるクラスから。
1: Imports System.Activities
2: Imports System.IO
3: Imports System.Net
4: Imports System.Security.Cryptography.X509Certificates
5:
6: Public MustInherit Class SQLAzureActivityBase
7: Inherits AsyncCodeActivity
8:
9: Protected Const SQL_API_PATH = "https://management.database.windows.net:8443/{0}/servers/{1}/firewallrules"
10:
11: Public Property SubscriptionID As String
12: Public Property CertThumbPrint As String
13:
14: Public Property ServerName As String
15: Public Property RuleName As String
16: Public Property StartIP As String
17: Public Property EndIP As String
18:
19: Public Property ResultDocument As OutArgument(Of String)
20: Public Property ResultStatus As OutArgument(Of String)
21: Public Property RequestID As OutArgument(Of String)
22:
23: Private Delegate Function AsyncGetWebDataDelegate(ByVal subscription As String,
24: ByVal thumbprint As String) As String()
25:
26: Protected Overrides Function BeginExecute(context As System.Activities.AsyncCodeActivityContext, callback As System.AsyncCallback, state As Object) As System.IAsyncResult
27: Dim asyncExecute = New AsyncGetWebDataDelegate(AddressOf GetWebData)
28: context.UserState = asyncExecute
29:
30: Return asyncExecute.BeginInvoke(Me.SubscriptionID, Me.CertThumbPrint, callback, state)
31: End Function
32:
33: Protected Overrides Sub EndExecute(context As System.Activities.AsyncCodeActivityContext, result As System.IAsyncResult)
34: Dim asyncExecute = TryCast(context.UserState, AsyncGetWebDataDelegate)
35: Dim getResult = asyncExecute.EndInvoke(result)
36:
37: context.SetValue(Me.ResultDocument, getResult(0))
38: context.SetValue(Me.ResultStatus, getResult(1))
39: context.SetValue(Me.RequestID, getResult(2))
40: End Sub
41:
42: Protected Overridable Function GetWebData(ByVal subscription As String,
43: ByVal thumbprint As String) As String()
44: Dim resultStrings As String = ""
45: Dim resultStatus As String = ""
46: Dim resultRequestID As String = ""
47: Try
48: Dim certificate As X509Certificate2 = CreateCertification(thumbprint)
49:
50: Dim requestUri As Uri = Me.CreateApiPath(subscription, Me.RuleName)
51: Dim localWebRequest = TryCast(HttpWebRequest.Create(requestUri), HttpWebRequest)
52: localWebRequest.ClientCertificates.Add(certificate)
53: Me.SetHttpMethod(localWebRequest)
54: Me.AddRequestHeader(localWebRequest)
55:
56: Dim bodyString = Me.CreateBodyMessage()
57: If bodyString IsNot Nothing Then
58: Dim sendBytes() As Byte = Text.Encoding.UTF8.GetBytes(bodyString)
59: localWebRequest.ContentLength = sendBytes.Length
60: localWebRequest.ContentType = "application/xml; charset=utf-8"
61: Using reqStream = localWebRequest.GetRequestStream
62: reqStream.Write(sendBytes, 0, sendBytes.Length)
63: End Using
64: End If
65:
66: Using webResponse = TryCast(localWebRequest.GetResponse(), HttpWebResponse)
67: resultStatus = webResponse.StatusCode.ToString
68: resultRequestID = webResponse.Headers("x-ms-request-id")
69: Using responseStream = webResponse.GetResponseStream()
70: Using reader As New StreamReader(responseStream)
71: resultStrings = reader.ReadToEnd
72: End Using
73: End Using
74: End Using
75:
76: Catch ex As Exception
77: resultStrings = ex.Message
78: End Try
79: Return New String() {resultStrings, resultStatus, resultRequestID}
80: End Function
81:
82: Protected Overridable Function CreateApiPath(subscript As String, ByVal rule As String) As System.Uri
83: Return New Uri(String.Format(SQL_API_PATH, subscript, Me.ServerName) +
84: "/" + rule)
85: End Function
86:
87: Protected Overridable Function CreateCertification(ByVal thumbPrintString As String) As X509Certificate2
88: Dim certStore As X509Store = New X509Store(StoreName.My, StoreLocation.CurrentUser)
89: certStore.Open(OpenFlags.ReadOnly)
90:
91: Dim certCollection As X509Certificate2Collection = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbPrintString, False)
92: certStore.Close()
93:
94: If certCollection.Count <= 0 Then
95: Throw New ApplicationException("証明書がありません")
96: End If
97: Return certCollection(0)
98: End Function
99:
100: Protected Overridable Sub AddRequestHeader(ByVal wq As WebRequest)
101: wq.Headers.Add("x-ms-version", "1.0")
102: End Sub
103:
104: Protected Overridable Sub SetHttpMethod(ByVal wq As WebRequest)
105: wq.Method = "PUT"
106: End Sub
107:
108: Protected Overridable Function CreateBodyMessage() As String
109: Dim xmlBody =
110: "<?xml version=""1.0"" encoding=""utf-8""?>" + ControlChars.NewLine +
111: "<FirewallRule" + ControlChars.NewLine +
112: " xmlns=""http://schemas.microsoft.com/sqlazure/2010/12/""" + ControlChars.NewLine +
113: " xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""" + ControlChars.NewLine +
114: " xsi:schemaLocation=""http://schemas.microsoft.com/sqlazure/2010/12/ FirewallRule.xsd"">" + ControlChars.NewLine +
115: " <StartIpAddress>" + Me.StartIP + "</StartIpAddress>" + ControlChars.NewLine +
116: " <EndIpAddress>" + Me.EndIP + "</EndIpAddress>" + ControlChars.NewLine +
117: "</FirewallRule>"
118: Return xmlBody
119: End Function
120:
121: End Class
今回ベースにしている処理はファイアウォールルールの新規追加です。ですので新規追加用アクティビティはこのベースクラス自体を利用してもよかったのですが、あとでリファクタリングを行う事を考えて、そのままにしていますw
1: Imports System.Activities
2:
3: Public Class CreateSQLAzureFirewallRuleActivity
4: Inherits SQLAzureActivityBase
5:
6: Public Sub New()
7: Me.DisplayName = "SQLAzure FW ルール作成"
8: End Sub
9:
10: End Class
続いて列挙。
1: Imports System.Activities
2:
3: Public Class EnumSQLAzureFirewallRuleActivity
4: Inherits SQLAzureActivityBase
5:
6: Public Sub New()
7: Me.DisplayName = "SQLAzure FW ルール列挙"
8: End Sub
9:
10: Protected Overrides Sub SetHttpMethod(wq As System.Net.WebRequest)
11: wq.Method = "GET"
12: End Sub
13:
14: Protected Overrides Function CreateBodyMessage() As String
15: Return Nothing
16: End Function
17:
18: Protected Overrides Function CreateApiPath(subscript As String, rule As String) As System.Uri
19: Return New Uri(String.Format(SQL_API_PATH, subscript, Me.ServerName))
20: End Function
21:
22: End Class
最後に削除です。
1: Imports System.Activities
2:
3: Public Class DeleteSQLAzureFirewallRuleActivity
4: Inherits SQLAzureActivityBase
5:
6: Public Sub New()
7: Me.DisplayName = "SQLAzure FW ルール削除"
8: End Sub
9:
10: Protected Overrides Sub SetHttpMethod(wq As System.Net.WebRequest)
11: wq.Method = "DELETE"
12: End Sub
13:
14: Protected Overrides Function CreateBodyMessage() As String
15: Return Nothing
16: End Function
17:
18: End Class
なお、これら 3 つのアクティビティにて、実行時に結果が返却されるものは「列挙」のみです。「作成」と「削除」は特に処理結果を返却しませんので、HTTP のステータスコードにより結果を判断するようにしてください。基本的には 200 が返却されれば正常終了です。
これら 3 つのアクティビティを、ワークフロー上で実際に利用した場合のプロパティ設定はこのような形になります。
作成時はほぼすべてのプロパティに設定する必要があります。ただし結果関係のプロパティとして実装している、ResultDocument、ResultStatus、RequestID プロパティについては未設定でも利用可能です。
列挙時はこのように、ルールの設定に関わる部分が未設定となります。
実行して返却される結果はこのような感じになります。
削除の際は、削除対象となるルール名が必要ですが、開始~終了の IP アドレスについては未設定で利用できます。
このような形で SQL Azure 管理 REST API をアクティビティ化し利用する事で、ファイアウォールのルール設定が簡易に行えるようになります。
0 件のコメント:
コメントを投稿