Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
SQL 数据库管理 API 可以编程方式访问与通过 Windows Azure 平台管理门户执行的相同管理操作,来管理 Windows Azure SQL服务器。使用 SQL 数据库管理 API 可以管理每个订阅的 SQL Database 服务器以及与每台服务器关联的防火墙规则。这有助于自动化应用程序的数据库支持,而无需直接与管理门户进行交互。
数据库管理 API 是一个 REST API。所发送的操作请求通过 SSL 进行加密,并使用 X.509 证书对其进行身份验证。可以通过 Internet 从可以发送 HTTPS 请求和接收 HTTPS 响应的任何应用程序发出这些请求。请求将发送到使用以下基本 URL 的端口 8443 上的 SQL Database 数据库管理服务:https://management.database.windows.net:8443
这个blog介绍了以编程方式 (使用 Visual Studio 2012 RC 中的 HttpClient) 创建一个Windows Azure SQL 数据库服务器,设置管理密码,并创建防火墙规则。我们可以使用如下步骤:
- 准备访问数据库管理 API 的客户端证书。
- 设置相应的HTTP请求标头,如版本号等。
- 创建数据库服务器
- 定义请求数据的 .net 对象
- 发送请求,并接收服务器响应数据
- 将响应数据转换为 .net (如C#) 的相应对象
- 从对象中读取信息
- 设置管理密码
- 创建防火墙规则
- 连接到新创建的数据库服务器
1、准备客户端证书
数据库管理 API 需要基于证书的相互身份验证。我们需要首先将公钥证书(.cer)文件与订阅相关联,方法是使用 Windows Azure 平台管理门户将该证书上载到 Windows Azure 中订阅的证书存储区。然后,将匹配的私钥证书(.pfx)文件附加到数据库管理 API 请求中。
有关证书创建,可以参考 如何创建管理证书 以及 如何为角色创建证书。例如,可以使用MakeCert工具,具体命令可参考 Step 1 - Create and Install a test certificate 。
进而我们可以获得 .cer 文件(包含公钥) 和 .pfx 文件 (包含私钥和公钥,私钥保护密码由用户指定),可以使用管理门户将公钥证书 (.cer 文件)上载到 Windows Azure中订阅的证书存储区,如:
之后,可以使用 System.Net.Http.WebRequestHandler 和 System.Security.Cryptography.X509Certificate2 .NET 类将私钥 (.pfx) 文件与安全请求相关联。
如以下代码片段,其中参数certFilename 和certPassword 分别是 .pfx 文件的全路径文件名和私钥保护密码 (私钥和密码不与请求一起发送;它们仅用于对请求进行验证):
WebRequestHandler webRequestHandler = new WebRequestHandler();
webRequestHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
webRequestHandler.ClientCertificates.Add(
new X509Certificate2(certFilename, certPassword));
2、设置相应的HTTP请求标头
HttpClient可用于发送 Http 请求,并用于接收 Http 响应。如下代码片段生成一个HttpClient实例,并设置访问 API 的版本信息:
this.httpClient = new HttpClient(webRequestHandler);
this.httpClient.DefaultRequestHeaders.Add("x-ms-version", "1.0");
完整代码片段如下:
public class SqlRestApiClient
{
private const string ServerUri = "https://management.database.windows.net:8443/{0}/servers";
private const string FirewallUri = ServerUri + "/{1}/firewallrules";
private readonly string subscriptionId;
private readonly HttpClient httpClient;
private readonly XmlMediaTypeFormatter xmlFormatter;
private readonly IEnumerable<XmlMediaTypeFormatter> xmlFormatters;
public SqlRestApiClient(string certFilename, string certPassword, string subscriptionId)
{
WebRequestHandler webRequestHandler = new WebRequestHandler();
webRequestHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
webRequestHandler.ClientCertificates.Add(
new X509Certificate2(certFilename, certPassword));
this.httpClient = new HttpClient(webRequestHandler);
this.httpClient.DefaultRequestHeaders.Add("x-ms-version", "1.0");
this.xmlFormatter = new XmlMediaTypeFormatter()
{
UseXmlSerializer = true,
};
this.xmlFormatters = new XmlMediaTypeFormatter[] { xmlFormatter };
this.subscriptionId = subscriptionId;
}
}
3、创建数据库服务器
定义请求数据的 .net 对象
定义请求数据 .Net 对象 ServerRequest如下:
[XmlRoot(ElementName = "Server",
Namespace = "https://schemas.microsoft.com/sqlazure/2010/12/")]
public class ServerRequest
{
public string AdministratorLogin { get; set; }
public string AdministratorLoginPassword { get; set; }
public string Location { get; set; }
}
发送请求并接收服务器响应数据
设置枚举服务器的url,其中需要指定 Windows Azure 的订阅ID (参数:subscriptionId);构建请求数据:
string url = string.Format(ServerUri, this.subscriptionId);
var request = new ServerRequest()
{
AdministratorLogin = adminName,
AdministratorLoginPassword = adminPwd,
Location = location,
};
设置Xml媒体类型序列化器,然后发送HTTP POST请求,并读取响应正文。
HttpResponseMessage response = await this.httpClient
.PostAsync<ServerRequest>(url, request, this.xmlFormatter);
将响应数据转换为 .net (如C#) 的相应对象
我们可以定义 .net 对象ServerName如下:
[XmlRoot(ElementName = "ServerName",
Namespace = "https://schemas.microsoft.com/sqlazure/2010/12/")]
public class CreateServerResponse
{
[XmlText]
public string ServerName { get; set; }
}
将响应正文数据转换为 C# 对象:
CreateServerResponse server = await response.Content
.ReadAsAsync<CreateServerResponse>(this.xmlFormatters);
从对象中读取信息
例如我们可以读取 server.ServerName 信息,如下:
Console.WriteLine("ServerName: {0}", server.ServerName);
创建SQL数据库服务器的完整代码片段如下:
async public Task CreateServer(string adminName, string adminPwd, string location)
{
string url = string.Format(ServerUri, this.subscriptionId);
var request = new ServerRequest()
{
AdministratorLogin = adminName,
AdministratorLoginPassword = adminPwd,
Location = location,
};
HttpResponseMessage response = await this.httpClient
.PostAsync<ServerRequest>(url, request, this.xmlFormatter);
if (!response.IsSuccessStatusCode)
{
this.ErrorHandler(response);
return;
}
CreateServerResponse server = await response.Content
.ReadAsAsync<CreateServerResponse>(this.xmlFormatters);
Console.WriteLine("ServerName: {0}", server.ServerName);
}
private async void ErrorHandler(HttpResponseMessage response)
{
Console.WriteLine("Caught HttpResponseException");
Error error = await response.Content
.ReadAsAsync<Error>(this.xmlFormatters);
Console.WriteLine(
"Code: {0}, Message: {1}, Severity: {2}, State: {3}",
error.Code,
error.Message,
error.Severity,
error.State);
}
其中Error定义如下:
[XmlRoot(Namespace = "https://schemas.microsoft.com/sqlazure/2010/12/")]
public class Error
{
public uint Code { get; set; }
public string Message { get; set; }
public uint Severity { get; set; }
public uint State { get; set; }
}
调用方式如下:
SqlRestApiClient sqlRestApiClient = new SqlRestApiClient(
"windows_azure_tools.pfx",
"certPassword",
"c4a83956-af86-4606-8881-d12c0ae12ea6");
await sqlRestApiClient.CreateServer("adm1", "Pa$$word123$$", "North Central US");
例如,输出如下:
ServerName: ux5zdppgom
也可以登录Windows Azure管理门户查看新创建的SQL数据库服务器:
4、设置管理密码
在前面创建SQL数据库服务器时我们设置了管理员帐户名称和密码,过后我们可使用“设置服务器管理员密码” REST API重新设置 SQL 数据库服务器的管理密码。
我们可以定义重置密码请求的对象如下:
[XmlRoot(ElementName = "AdministratorLoginPassword",
Namespace = "https://schemas.microsoft.com/sqlazure/2010/12/")]
public class AdministratorLoginPasswordRequest
{
[XmlText]
public string AdministratorLoginPassword { get; set; }
}
重置密码方法如创建SQL服务器类似。先设定请求的Url,创建请求消息,然后发送请求,接收响应数据。
设置管理密码的代码片段如下:
async public Task ResetPassword(string serverName, string password)
{
string url = string.Format(ServerUri + "/{1}?op=ResetPassword",
this.subscriptionId,
serverName);
var request = new AdministratorLoginPasswordRequest()
{
AdministratorLoginPassword = password,
};
HttpResponseMessage response = await this.httpClient
.PostAsync(url, request, this.xmlFormatter);
if (response.IsSuccessStatusCode)
{
Console.WriteLine(
"server: {0}, password {1} is reset successfully",
serverName,
password);
}
else
{
this.ErrorHandler(response);
}
}
调用方式如下:
await sqlRestApiClient.ResetPassword("ux5zdppgom", "Pa$word123$");
输出如下:
server: ux5zdppgom, password Pa$word123$ is reset successfully
5、创建防火墙规则
为服务器创建防火墙规则
默认情况下,新创建的SQL服务器禁止来自客户端的访问。我们可以为服务器创建防火墙规则,以允许来之客户端,或/和允许从与 Windows Azure 相关的应用程序和服务连接到服务器。
防火墙规则对象可定义如下:
[XmlRoot(ElementName = "FirewallRule",
Namespace = "https://schemas.microsoft.com/sqlazure/2010/12/")]
public class FirewallRuleRequest
{
public string StartIpAddress { get; set; }
public string EndIpAddress { get; set; }
}
使用类似设置管理密码的流程,一个不同之处是:我们需要发送HTTP PUT请求,而不是POST请求。代码片段如下:
async public Task CreateFirewallRule(string serverName, string ruleName, string startIp, string endIp)
{
string url = string.Format(FirewallUri + "/{2}",
this.subscriptionId,
serverName,
ruleName);
var request = new FirewallRuleRequest()
{
StartIpAddress = startIp,
EndIpAddress = endIp,
};
HttpResponseMessage response = await this.httpClient
.PutAsync(url, request, this.xmlFormatter);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("rule: {0} [{1} - {2}] written successfully",
ruleName,
startIp,
endIp);
}
else
{
this.ErrorHandler(response);
}
}
调用方式如下:
await sqlRestApiClient.CreateFirewallRule("ux5zdppgom", "rule1", "0.0.0.0", "0.0.0.0");
输出如下:
rule: rule1 [0.0.0.0 - 0.0.0.0] written successfully
其中起始和结束 IP 地址设置为 0.0.0.0 的防火墙规则允许从与 Windows Azure 相关的应用程序和服务连接到服务器。
使用 IP 检测为服务器创建防火墙规则
我们还可以使用 IP 检测为服务器创建防火墙规则。当用户由于地址转换、代理服务器等原因不知道自己的外部 IP 地址时,这可能会有用。方法与如上类似,先定义一个IpAddress对象:
[XmlRoot(ElementName = "IpAddress",
Namespace = "https://schemas.microsoft.com/sqlazure/2010/12/")]
public class IpAddressResponse
{
[XmlText]
public string IpAddress { get; set; }
}
代码如下:
async public Task CreateFirewallRuleWithClientIp(string serverName, string ruleName)
{
string url = string.Format(FirewallUri + "/{2}?op=AutoDetectClientIP",
this.subscriptionId,
serverName,
ruleName);
var requestMessage = new HttpRequestMessage();
HttpResponseMessage response = await this.httpClient
.PostAsync(url, requestMessage.Content);
if (!response.IsSuccessStatusCode)
{
this.ErrorHandler(response);
return;
}
IpAddressResponse ip = await response.Content
.ReadAsAsync<IpAddressResponse>(this.xmlFormatters);
Console.WriteLine("rule: {0} added with client ip: {1}",
ruleName,
ip.IpAddress);
}
调用方式可以为:
await sqlRestApiClient.CreateFirewallRuleWithClientIp("ux5zdppgom", "rule2");
输出如下:
rule: rule2 added with client ip: 116.96.128.226
6、连接到新创建的数据库服务器
我们可以使用SQL Server Management Studio (SSMS) 连接到如上新创建的SQL数据库服务器。
输入服务器名称,验证方式选择为:SQL Server Authentication,然后输入用户名和密码。
点击连接,连接成功后我们可以看到:
有关SQL Database 数据库管理 API的更多信息,可以参考msdn中相应内容 。
软件开发工程师 苏从勇