C# から APIC-EM の REST API にアクセスする
Cisco Japan Blog の SDN カテゴリー に「Python を使って APIC-EM の REST API にアクセスする」という記事が掲載されています。
(APIC-EM に限らず) Python や Ruby から REST API にアクセスするサンプルはしばしば見かけるのですが、C# のサンプルはなぜか数が少ないきがします… (探し方が悪い?)。というわけで C# のサンプルを書いてみました。あくまでサンプルなのでエラー処理はしていません。
処理の大まかな流れ
実際に何がしかの REST API を利用する前に「ServiceTicket」と呼ばれる資格情報を取得する必要があります。よって、大まかな処理順序は以下のようになります。
- 適切な ID/Password を使って ServiceTicket を取得する
- 取得出来た ServiceTicket を使って必要な REST API を呼び出す
サンプルコード
やや長いですが、今回のサンプルコード全体は以下の通りです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 | using System;
using System.Net;
using System.Runtime.Serialization;
using RestSharp;
namespace RestApiSample
{
class LoginInfo
{
public string username { get; set; }
public string password { get; set; }
public LoginInfo(string _username, string _password)
{
username = _username;
password = _password;
}
}
[DataContract]
class ServiceTicket
{
[DataMember]
public ServiceTicketResponse response { get; set; }
[DataMember]
public float version { get; set; }
}
[DataContract]
class ServiceTicketResponse
{
[DataMember]
public string serviceTicket { get; set; }
[DataMember]
public uint idleTimeout { get; set; }
[DataMember]
public uint sessionTimeout { get; set; }
}
[DataContract]
class NetworkDeviceCount
{
[DataMember]
public uint response { get; set; }
public float version { get; set; }
}
class Program
{
static void Main(string[] args)
{
// Ignore self-signed SSL certificate warnings.
ServicePointManager.ServerCertificateValidationCallback += (
sender,
certificate,
chain,
sslPolicyErrors) => true;
string baseUrl = "https://10.0.0.1";
string username = "admin";
string password = "password";
// Get Service Ticket.
string serviceTicket = GetServiceTicket(baseUrl, username, password);
// Get network device count.
NetworkDeviceCount networkDeviceCount = GetNetworkDevivceCount(baseUrl, serviceTicket);
Console.WriteLine(networkDeviceCount.response);
}
static string GetServiceTicket(string _baseUrl, string _username, string _password)
{
var client = new RestClient(_baseUrl);
LoginInfo loginInfo = new LoginInfo(_username, _password);
var request = new RestRequest("api/v1/ticket", Method.POST);
request.RequestFormat = DataFormat.Json;
request.AddBody(loginInfo);
IRestResponse response = client.Execute(request);
RestSharp.Deserializers.JsonDeserializer deserializer =
new RestSharp.Deserializers.JsonDeserializer();
var serviceTicket = deserializer.Deserialize<ServiceTicket>(response).response;
return serviceTicket.serviceTicket;
}
static NetworkDeviceCount GetNetworkDevivceCount(string _baseUrl, string _serviceTicket)
{
var client = new RestClient(_baseUrl);
var request = new RestRequest("api/v1/network-device/count", Method.GET);
request.AddHeader("X-Auth-Token", _serviceTicket);
IRestResponse response = client.Execute(request);
RestSharp.Deserializers.JsonDeserializer deserializer =
new RestSharp.Deserializers.JsonDeserializer();
var networkDeviceCount = deserializer.Deserialize<NetworkDeviceCount>(response);
return networkDeviceCount;
}
}
}
|
補足説明
RestSharp で REST API を操作する
C# で使える REST API 関連のライブラリは幾つかあるようですが、今回は RestSharp を使いました。NuGet からインストールするなり、公式サイトからダウンロードしてプロジェクトへ参照を追加するなり、用意しておきます。
サーバ証明書の警告を無視する
APIC-EM はデフォルトで自己証明書を利用していますので、(当然ですが) そのままクライアントのブラウザからアクセスすると「証明書の正当性を確認出来ない」という警告が表示されます。C# から REST API で APIC-EM にアクセスした場合はエラーとなり、処理が継続出来ません。そこで証明書の警告を無視する為に以下のコードを追加しておきます。
| // Ignore self-signed SSL certificate warnings.
ServicePointManager.ServerCertificateValidationCallback += (
sender,
certificate,
chain,
sslPolicyErrors) => true;
|
データ構造をデータコントラクトとして定義する
Role Based Access Control の /ticket という API リファレンスを見ると Response Class は以下のように定義されています。
| TicketRbacResult {
version (string, optional),
response (ServiceTicketRbac, optional)
}
ServiceTicketRbac {
idleTimeout (integer, optional),
serviceTicket (string): Service Ticket to be used as authentication Ticket,
sessionTimeout (integer, optional)
}
|
実際にこの REST API (/api/v1/ticket) へ適切にアクセスすると、以下のような JSON のレスポンスを得られます。
| {"response":{"serviceTicket":"ST-59-u9Kxu6WzaXUUejbhfc24-cas","idleTimeout":1800,"sessionTimeout":21600},"version":"1.0"}
|
これをインデントすると以下のようになります。
| {
"response": {
"idleTimeout": 1800,
"serviceTicket": "ST-59-u9Kxu6WzaXUUejbhfc24-cas",
"sessionTimeout": 21600
},
"version": "1.0"
}
|
これを C# のデータコントラクトとして表現すると以下のように書けます。適当に書いてしまったのでクラス名が API リファレンスと一致していません… orz゛
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | [DataContract]
class ServiceTicket
{
[DataMember]
public ServiceTicketResponse response { get; set; }
[DataMember]
public float version { get; set; }
}
[DataContract]
class ServiceTicketResponse
{
[DataMember]
public string serviceTicket { get; set; }
[DataMember]
public uint idleTimeout { get; set; }
[DataMember]
public uint sessionTimeout { get; set; }
}
|
POST 時のリクエストボディの書き方
今回は POST する際、リクエストボディを以下のように書きました。request は RestSharp.RestRequest クラスのインスタンスです。
| LoginInfo loginInfo = new LoginInfo("admin", "password");
var request = new RestRequest("api/v1/ticket", Method.POST);
request.RequestFormat = DataFormat.Json;
request.AddBody(loginInfo);
|
これは以下のように書くことも出来ます。
| request.AddParameter(
"application/json",
"{\"username\": \"admin\", \"password\": \"password\"}",
ParameterType.RequestBody
);
|