SQL数据库管理API简介
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中相应内容 。
软件开发工程师 苏从勇