Merge lp:~mark-sheahan-ms/gwacl/cert-args into lp:gwacl
- cert-args
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 238 |
Proposed branch: | lp:~mark-sheahan-ms/gwacl/cert-args |
Merge into: | lp:gwacl |
Diff against target: |
221 lines (+94/-10) 3 files modified
management_base.go (+44/-1) management_base_test.go (+30/-6) x509session.go (+20/-3) |
To merge this branch: | bzr merge lp:~mark-sheahan-ms/gwacl/cert-args |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrew Wilkins (community) | Approve | ||
Review via email: mp+235889@code.launchpad.net |
Commit message
Add functions to instantiate a new management API, with the certificate+key provided as input byte arrays rather than a file path.
Description of the change
Add functions to instantiate a new management API, with the certificate+key provided as input byte arrays rather than a file path.
func NewManagementAP
func NewManagementAP
Andrew Wilkins (axwalk) wrote : | # |
Andrew Wilkins (axwalk) : | # |
Mark Sheahan (mark-sheahan-ms) wrote : | # |
Thanks Andrew. I have signed the agreement as a contributor from ScriptRock
Inc.
What are the next steps for submission back into trunk? I haven't used
Bazaar or launchpad until yesterday.
Regards,
Mark
On Thu, Sep 25, 2014 at 12:05 AM, Andrew Wilkins <
<email address hidden>> wrote:
> Review: Approve
>
>
> --
> https:/
> You are the owner of lp:~mark-sheahan-ms/gwacl/cert-args.
>
Andrew Wilkins (axwalk) wrote : | # |
Landing requires someone from the "GWACL Hackers" group (e.g. me) to push it through. I'll handle it from here. Thanks again.
Go Bot (go-bot) wrote : | # |
The attempt to merge lp:~mark-sheahan-ms/gwacl/cert-args into lp:gwacl failed. Below is the output from the failed tests.
/bin/sh: 1: Syntax error: "&&" unexpected
Andrew Wilkins (axwalk) wrote : | # |
I'll need to get in touch with the maintainer of the landing bot to see what's going on there.
Andrew Wilkins (axwalk) wrote : | # |
I went ahead and merged manually. Thanks again.
Mark Sheahan (mark-sheahan-ms) wrote : | # |
Thanks Andrew; hopefully we can contribute more as we use it more
extensively.
On Tue, Sep 30, 2014 at 6:09 PM, Andrew Wilkins <
<email address hidden>> wrote:
> I went ahead and merged manually. Thanks again.
> --
> https:/
> You are the owner of lp:~mark-sheahan-ms/gwacl/cert-args.
>
Preview Diff
1 | === modified file 'management_base.go' | |||
2 | --- management_base.go 2014-06-24 09:32:41 +0000 | |||
3 | +++ management_base.go 2014-09-25 02:19:41 +0000 | |||
4 | @@ -9,6 +9,7 @@ | |||
5 | 9 | "net/http" | 9 | "net/http" |
6 | 10 | "strings" | 10 | "strings" |
7 | 11 | "time" | 11 | "time" |
8 | 12 | "launchpad.net/gwacl/fork/tls" | ||
9 | 12 | ) | 13 | ) |
10 | 13 | 14 | ||
11 | 14 | // Note: each API call is required to include a version string in the request header. | 15 | // Note: each API call is required to include a version string in the request header. |
12 | @@ -37,7 +38,8 @@ | |||
13 | 37 | const DefaultPollerTimeout = 20 * time.Minute | 38 | const DefaultPollerTimeout = 20 * time.Minute |
14 | 38 | 39 | ||
15 | 39 | // NewManagementAPIWithRetryPolicy creates an object used to interact with | 40 | // NewManagementAPIWithRetryPolicy creates an object used to interact with |
17 | 40 | // Windows Azure's API. | 41 | // Windows Azure's API. Certificate data is provided through a file path; |
18 | 42 | // the file must contain the private key, then the certificate, both in PEM format. | ||
19 | 41 | // http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx | 43 | // http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx |
20 | 42 | func NewManagementAPIWithRetryPolicy(subscriptionId, certFile, location string, policy RetryPolicy) (*ManagementAPI, error) { | 44 | func NewManagementAPIWithRetryPolicy(subscriptionId, certFile, location string, policy RetryPolicy) (*ManagementAPI, error) { |
21 | 43 | session, err := newX509Session(subscriptionId, certFile, location, policy) | 45 | session, err := newX509Session(subscriptionId, certFile, location, policy) |
22 | @@ -49,11 +51,52 @@ | |||
23 | 49 | } | 51 | } |
24 | 50 | 52 | ||
25 | 51 | // NewManagementAPI creates an object used to interact with Windows Azure's API. | 53 | // NewManagementAPI creates an object used to interact with Windows Azure's API. |
26 | 54 | // Certificate data is provided through a file path; the file must contain the | ||
27 | 55 | // private key, then the certificate, both in PEM format. | ||
28 | 52 | // http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx | 56 | // http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx |
29 | 53 | func NewManagementAPI(subscriptionId, certFile, location string) (*ManagementAPI, error) { | 57 | func NewManagementAPI(subscriptionId, certFile, location string) (*ManagementAPI, error) { |
30 | 54 | return NewManagementAPIWithRetryPolicy(subscriptionId, certFile, location, NoRetryPolicy) | 58 | return NewManagementAPIWithRetryPolicy(subscriptionId, certFile, location, NoRetryPolicy) |
31 | 55 | } | 59 | } |
32 | 56 | 60 | ||
33 | 61 | // NewManagementAPICertDataWithRetryPolicy creates an object used to interact with | ||
34 | 62 | // Windows Azure's API. Certificate and private key data are provided through input | ||
35 | 63 | // byte arrays, each containing data in PEM format. | ||
36 | 64 | // http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx | ||
37 | 65 | func NewManagementAPICertDataWithRetryPolicy(subscriptionId string, cert, key []byte, location string, policy RetryPolicy) (*ManagementAPI, error) { | ||
38 | 66 | session, err := newX509SessionCertData(subscriptionId, cert, key, location, policy) | ||
39 | 67 | if err != nil { | ||
40 | 68 | return nil, err | ||
41 | 69 | } | ||
42 | 70 | api := ManagementAPI{session, DefaultPollerInterval, DefaultPollerTimeout} | ||
43 | 71 | return &api, nil | ||
44 | 72 | } | ||
45 | 73 | |||
46 | 74 | // NewManagementAPICertData creates an object used to interact with Windows Azure's API. | ||
47 | 75 | // Certificate and private key data are provided through input byte arrays, | ||
48 | 76 | // each containing data in PEM format. | ||
49 | 77 | // http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx | ||
50 | 78 | func NewManagementAPICertData(subscriptionId string, cert, key []byte, location string) (*ManagementAPI, error) { | ||
51 | 79 | return NewManagementAPICertDataWithRetryPolicy(subscriptionId, cert, key, location, NoRetryPolicy) | ||
52 | 80 | } | ||
53 | 81 | |||
54 | 82 | // NewManagementAPICertsWithRetryPolicy creates an object used to interact with | ||
55 | 83 | // Windows Azure's API. | ||
56 | 84 | // http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx | ||
57 | 85 | func NewManagementAPICertsWithRetryPolicy(subscriptionId string, certs []tls.Certificate, location string, policy RetryPolicy) (*ManagementAPI, error) { | ||
58 | 86 | session, err := newX509SessionCerts(subscriptionId, certs, location, policy) | ||
59 | 87 | if err != nil { | ||
60 | 88 | return nil, err | ||
61 | 89 | } | ||
62 | 90 | api := ManagementAPI{session, DefaultPollerInterval, DefaultPollerTimeout} | ||
63 | 91 | return &api, nil | ||
64 | 92 | } | ||
65 | 93 | |||
66 | 94 | // NewManagementAPICerts creates an object used to interact with Windows Azure's API. | ||
67 | 95 | // http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx | ||
68 | 96 | func NewManagementAPICerts(subscriptionId string, certs []tls.Certificate, location string) (*ManagementAPI, error) { | ||
69 | 97 | return NewManagementAPICertsWithRetryPolicy(subscriptionId, certs, location, NoRetryPolicy) | ||
70 | 98 | } | ||
71 | 99 | |||
72 | 57 | var operationIDHeaderName = http.CanonicalHeaderKey("x-ms-request-id") | 100 | var operationIDHeaderName = http.CanonicalHeaderKey("x-ms-request-id") |
73 | 58 | 101 | ||
74 | 59 | // getOperationID extracts the Windows Azure operation ID from the headers | 102 | // getOperationID extracts the Windows Azure operation ID from the headers |
75 | 60 | 103 | ||
76 | === modified file 'management_base_test.go' | |||
77 | --- management_base_test.go 2014-03-12 03:56:53 +0000 | |||
78 | +++ management_base_test.go 2014-09-25 02:19:41 +0000 | |||
79 | @@ -4,6 +4,7 @@ | |||
80 | 4 | package gwacl | 4 | package gwacl |
81 | 5 | 5 | ||
82 | 6 | import ( | 6 | import ( |
83 | 7 | "bytes" | ||
84 | 7 | "encoding/base64" | 8 | "encoding/base64" |
85 | 8 | "encoding/xml" | 9 | "encoding/xml" |
86 | 9 | "errors" | 10 | "errors" |
87 | @@ -207,7 +208,7 @@ | |||
88 | 207 | c.Assert(err, IsNil) | 208 | c.Assert(err, IsNil) |
89 | 208 | } | 209 | } |
90 | 209 | 210 | ||
92 | 210 | var testCert = dedent.Dedent(` | 211 | var testKey = []byte(dedent.Dedent(` |
93 | 211 | -----BEGIN PRIVATE KEY----- | 212 | -----BEGIN PRIVATE KEY----- |
94 | 212 | MIIBCgIBADANBgkqhkiG9w0BAQEFAASB9TCB8gIBAAIxAKQGQxP1i0VfCWn4KmMP | 213 | MIIBCgIBADANBgkqhkiG9w0BAQEFAASB9TCB8gIBAAIxAKQGQxP1i0VfCWn4KmMP |
95 | 213 | taUFn8sMBKjP/9vHnUYdZRvvmoJCA1C6arBUDp8s2DNX+QIDAQABAjBLRqhwN4dU | 214 | taUFn8sMBKjP/9vHnUYdZRvvmoJCA1C6arBUDp8s2DNX+QIDAQABAjBLRqhwN4dU |
96 | @@ -216,6 +217,8 @@ | |||
97 | 216 | GBW7VXLxbExpgnhb1V97vjQmTfthXQjYAwIYSTEjoFXm4+Bk5xuBh2IidgSeGZaC | 217 | GBW7VXLxbExpgnhb1V97vjQmTfthXQjYAwIYSTEjoFXm4+Bk5xuBh2IidgSeGZaC |
98 | 217 | FFY9AhkAsteo31cyQw2xJ80SWrmsIw+ps7Cvt5W9 | 218 | FFY9AhkAsteo31cyQw2xJ80SWrmsIw+ps7Cvt5W9 |
99 | 218 | -----END PRIVATE KEY----- | 219 | -----END PRIVATE KEY----- |
100 | 220 | `[1:])) | ||
101 | 221 | var testCert = []byte(dedent.Dedent(` | ||
102 | 219 | -----BEGIN CERTIFICATE----- | 222 | -----BEGIN CERTIFICATE----- |
103 | 220 | MIIBDzCByqADAgECAgkAgIBb3+lSwzEwDQYJKoZIhvcNAQEFBQAwFTETMBEGA1UE | 223 | MIIBDzCByqADAgECAgkAgIBb3+lSwzEwDQYJKoZIhvcNAQEFBQAwFTETMBEGA1UE |
104 | 221 | AxQKQEhvc3ROYW1lQDAeFw0xMzA3MTkxNjA1NTRaFw0yMzA3MTcxNjA1NTRaMBUx | 224 | AxQKQEhvc3ROYW1lQDAeFw0xMzA3MTkxNjA1NTRaFw0yMzA3MTcxNjA1NTRaMBUx |
105 | @@ -224,20 +227,20 @@ | |||
106 | 224 | AAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADMQABKfn08tKfzzqMMD2w | 227 | AAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADMQABKfn08tKfzzqMMD2w |
107 | 225 | PI2fs3bw5bRH8tmGjrsJeEdp9crCBS8I3hKcxCkTTRTowdY= | 228 | PI2fs3bw5bRH8tmGjrsJeEdp9crCBS8I3hKcxCkTTRTowdY= |
108 | 226 | -----END CERTIFICATE----- | 229 | -----END CERTIFICATE----- |
110 | 227 | `[1:]) | 230 | `[1:])) |
111 | 231 | var testCertKey = bytes.Join([][]byte{testKey, testCert}, []byte{}) | ||
112 | 228 | 232 | ||
113 | 229 | func (suite *managementBaseAPISuite) TestNewManagementAPI(c *C) { | 233 | func (suite *managementBaseAPISuite) TestNewManagementAPI(c *C) { |
114 | 230 | subscriptionId := "subscriptionId" | 234 | subscriptionId := "subscriptionId" |
115 | 231 | certDir := c.MkDir() | 235 | certDir := c.MkDir() |
116 | 232 | certFile := certDir + "/cert.pem" | 236 | certFile := certDir + "/cert.pem" |
118 | 233 | err := ioutil.WriteFile(certFile, []byte(testCert), 0600) | 237 | err := ioutil.WriteFile(certFile, testCertKey, 0600) |
119 | 234 | c.Assert(err, IsNil) | 238 | c.Assert(err, IsNil) |
120 | 235 | 239 | ||
121 | 236 | api, err := NewManagementAPI(subscriptionId, certFile, "West US") | 240 | api, err := NewManagementAPI(subscriptionId, certFile, "West US") |
122 | 237 | c.Assert(err, IsNil) | 241 | c.Assert(err, IsNil) |
123 | 238 | 242 | ||
124 | 239 | c.Assert(api.session.subscriptionId, DeepEquals, subscriptionId) | 243 | c.Assert(api.session.subscriptionId, DeepEquals, subscriptionId) |
125 | 240 | c.Assert(api.session.certFile, DeepEquals, certFile) | ||
126 | 241 | c.Assert(api.session.retryPolicy, DeepEquals, NoRetryPolicy) | 244 | c.Assert(api.session.retryPolicy, DeepEquals, NoRetryPolicy) |
127 | 242 | } | 245 | } |
128 | 243 | 246 | ||
129 | @@ -245,7 +248,7 @@ | |||
130 | 245 | subscriptionId := "subscriptionId" | 248 | subscriptionId := "subscriptionId" |
131 | 246 | certDir := c.MkDir() | 249 | certDir := c.MkDir() |
132 | 247 | certFile := certDir + "/cert.pem" | 250 | certFile := certDir + "/cert.pem" |
134 | 248 | err := ioutil.WriteFile(certFile, []byte(testCert), 0600) | 251 | err := ioutil.WriteFile(certFile, testCertKey, 0600) |
135 | 249 | c.Assert(err, IsNil) | 252 | c.Assert(err, IsNil) |
136 | 250 | retryPolicy := RetryPolicy{NbRetries: 5, HttpStatusCodes: []int{409}, Delay: time.Minute} | 253 | retryPolicy := RetryPolicy{NbRetries: 5, HttpStatusCodes: []int{409}, Delay: time.Minute} |
137 | 251 | 254 | ||
138 | @@ -253,7 +256,28 @@ | |||
139 | 253 | c.Assert(err, IsNil) | 256 | c.Assert(err, IsNil) |
140 | 254 | 257 | ||
141 | 255 | c.Assert(api.session.subscriptionId, DeepEquals, subscriptionId) | 258 | c.Assert(api.session.subscriptionId, DeepEquals, subscriptionId) |
143 | 256 | c.Assert(api.session.certFile, DeepEquals, certFile) | 259 | c.Assert(api.session.retryPolicy, DeepEquals, retryPolicy) |
144 | 260 | c.Assert(api.GetRetryPolicy(), DeepEquals, retryPolicy) | ||
145 | 261 | } | ||
146 | 262 | |||
147 | 263 | func (suite *managementBaseAPISuite) TestNewManagementAPICertData(c *C) { | ||
148 | 264 | subscriptionId := "subscriptionId" | ||
149 | 265 | |||
150 | 266 | api, err := NewManagementAPICertData(subscriptionId, testCert, testKey, "West US") | ||
151 | 267 | c.Assert(err, IsNil) | ||
152 | 268 | |||
153 | 269 | c.Assert(api.session.subscriptionId, DeepEquals, subscriptionId) | ||
154 | 270 | c.Assert(api.session.retryPolicy, DeepEquals, NoRetryPolicy) | ||
155 | 271 | } | ||
156 | 272 | |||
157 | 273 | func (suite *managementBaseAPISuite) TestNewManagementAPICertDataWithRetryPolicy(c *C) { | ||
158 | 274 | subscriptionId := "subscriptionId" | ||
159 | 275 | retryPolicy := RetryPolicy{NbRetries: 5, HttpStatusCodes: []int{409}, Delay: time.Minute} | ||
160 | 276 | |||
161 | 277 | api, err := NewManagementAPICertDataWithRetryPolicy(subscriptionId, testCert, testKey, "West US", retryPolicy) | ||
162 | 278 | c.Assert(err, IsNil) | ||
163 | 279 | |||
164 | 280 | c.Assert(api.session.subscriptionId, DeepEquals, subscriptionId) | ||
165 | 257 | c.Assert(api.session.retryPolicy, DeepEquals, retryPolicy) | 281 | c.Assert(api.session.retryPolicy, DeepEquals, retryPolicy) |
166 | 258 | c.Assert(api.GetRetryPolicy(), DeepEquals, retryPolicy) | 282 | c.Assert(api.GetRetryPolicy(), DeepEquals, retryPolicy) |
167 | 259 | } | 283 | } |
168 | 260 | 284 | ||
169 | === modified file 'x509session.go' | |||
170 | --- x509session.go 2014-02-04 08:58:10 +0000 | |||
171 | +++ x509session.go 2014-09-25 02:19:41 +0000 | |||
172 | @@ -14,7 +14,6 @@ | |||
173 | 14 | 14 | ||
174 | 15 | type x509Session struct { | 15 | type x509Session struct { |
175 | 16 | subscriptionId string | 16 | subscriptionId string |
176 | 17 | certFile string | ||
177 | 18 | client *http.Client | 17 | client *http.Client |
178 | 19 | baseURL *url.URL | 18 | baseURL *url.URL |
179 | 20 | retryPolicy RetryPolicy | 19 | retryPolicy RetryPolicy |
180 | @@ -32,13 +31,32 @@ | |||
181 | 32 | func newX509Session(subscriptionId, certFile, location string, retryPolicy RetryPolicy) (*x509Session, error) { | 31 | func newX509Session(subscriptionId, certFile, location string, retryPolicy RetryPolicy) (*x509Session, error) { |
182 | 33 | certs := []tls.Certificate{} | 32 | certs := []tls.Certificate{} |
183 | 34 | if certFile != "" { | 33 | if certFile != "" { |
184 | 35 | // | ||
185 | 36 | cert, err := tls.LoadX509KeyPair(certFile, certFile) | 34 | cert, err := tls.LoadX509KeyPair(certFile, certFile) |
186 | 37 | if err != nil { | 35 | if err != nil { |
187 | 38 | return nil, err | 36 | return nil, err |
188 | 39 | } | 37 | } |
189 | 40 | certs = append(certs, cert) | 38 | certs = append(certs, cert) |
190 | 41 | } | 39 | } |
191 | 40 | return newX509SessionCerts(subscriptionId, certs, location, retryPolicy) | ||
192 | 41 | } | ||
193 | 42 | |||
194 | 43 | // newX509SessionCertData creates and returns a new x509Session based on credentials | ||
195 | 44 | // and X509 certificate byte arrays. | ||
196 | 45 | func newX509SessionCertData(subscriptionId string, cert, key []byte, location string, retryPolicy RetryPolicy) (*x509Session, error) { | ||
197 | 46 | certs := []tls.Certificate{} | ||
198 | 47 | if cert != nil && key != nil { | ||
199 | 48 | cert, err := tls.X509KeyPair(cert, key) | ||
200 | 49 | if err != nil { | ||
201 | 50 | return nil, err | ||
202 | 51 | } | ||
203 | 52 | certs = append(certs, cert) | ||
204 | 53 | } | ||
205 | 54 | return newX509SessionCerts(subscriptionId, certs, location, retryPolicy) | ||
206 | 55 | } | ||
207 | 56 | |||
208 | 57 | // newX509SessionCerts creates and returns a new x509Session based on credentials | ||
209 | 58 | // and X509 certificate files. | ||
210 | 59 | func newX509SessionCerts(subscriptionId string, certs []tls.Certificate, location string, retryPolicy RetryPolicy) (*x509Session, error) { | ||
211 | 42 | client := http.Client{ | 60 | client := http.Client{ |
212 | 43 | Transport: &http.Transport{ | 61 | Transport: &http.Transport{ |
213 | 44 | TLSClientConfig: &tls.Config{ | 62 | TLSClientConfig: &tls.Config{ |
214 | @@ -66,7 +84,6 @@ | |||
215 | 66 | 84 | ||
216 | 67 | session := x509Session{ | 85 | session := x509Session{ |
217 | 68 | subscriptionId: subscriptionId, | 86 | subscriptionId: subscriptionId, |
218 | 69 | certFile: certFile, | ||
219 | 70 | client: &client, | 87 | client: &client, |
220 | 71 | baseURL: baseURL, | 88 | baseURL: baseURL, |
221 | 72 | retryPolicy: retryPolicy, | 89 | retryPolicy: retryPolicy, |
Thank you. I've been meaning to do this for a while, but never got around to it. This looks good to land as is. Can you please take a moment to sign the CLA? http:// www.ubuntu. com/legal/ contributors