Merge lp:~mark-sheahan-ms/gwacl/cert-args into lp:gwacl

Proposed by Mark Sheahan
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
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 NewManagementAPICertDataWithRetryPolicy(subscriptionId string, cert, key []byte, location string, policy RetryPolicy) (*ManagementAPI, error)

func NewManagementAPICertData(subscriptionId string, cert, key []byte, location string) (*ManagementAPI, error)

To post a comment you must log in.
Revision history for this message
Andrew Wilkins (axwalk) wrote :

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

Revision history for this message
Andrew Wilkins (axwalk) :
review: Approve
Revision history for this message
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://code.launchpad.net/~mark-sheahan-ms/gwacl/cert-args/+merge/235889
> You are the owner of lp:~mark-sheahan-ms/gwacl/cert-args.
>

Revision history for this message
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.

Revision history for this message
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

Revision history for this message
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.

Revision history for this message
Andrew Wilkins (axwalk) wrote :

I went ahead and merged manually. Thanks again.

Revision history for this message
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://code.launchpad.net/~mark-sheahan-ms/gwacl/cert-args/+merge/235889
> You are the owner of lp:~mark-sheahan-ms/gwacl/cert-args.
>

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'management_base.go'
--- management_base.go 2014-06-24 09:32:41 +0000
+++ management_base.go 2014-09-25 02:19:41 +0000
@@ -9,6 +9,7 @@
9 "net/http"9 "net/http"
10 "strings"10 "strings"
11 "time"11 "time"
12 "launchpad.net/gwacl/fork/tls"
12)13)
1314
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.
@@ -37,7 +38,8 @@
37const DefaultPollerTimeout = 20 * time.Minute38const DefaultPollerTimeout = 20 * time.Minute
3839
39// NewManagementAPIWithRetryPolicy creates an object used to interact with40// NewManagementAPIWithRetryPolicy creates an object used to interact with
40// Windows Azure's API.41// Windows Azure's API. Certificate data is provided through a file path;
42// the file must contain the private key, then the certificate, both in PEM format.
41// http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx43// http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx
42func NewManagementAPIWithRetryPolicy(subscriptionId, certFile, location string, policy RetryPolicy) (*ManagementAPI, error) {44func NewManagementAPIWithRetryPolicy(subscriptionId, certFile, location string, policy RetryPolicy) (*ManagementAPI, error) {
43 session, err := newX509Session(subscriptionId, certFile, location, policy)45 session, err := newX509Session(subscriptionId, certFile, location, policy)
@@ -49,11 +51,52 @@
49}51}
5052
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.
54// Certificate data is provided through a file path; the file must contain the
55// private key, then the certificate, both in PEM format.
52// http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx56// http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx
53func NewManagementAPI(subscriptionId, certFile, location string) (*ManagementAPI, error) {57func NewManagementAPI(subscriptionId, certFile, location string) (*ManagementAPI, error) {
54 return NewManagementAPIWithRetryPolicy(subscriptionId, certFile, location, NoRetryPolicy)58 return NewManagementAPIWithRetryPolicy(subscriptionId, certFile, location, NoRetryPolicy)
55}59}
5660
61// NewManagementAPICertDataWithRetryPolicy creates an object used to interact with
62// Windows Azure's API. Certificate and private key data are provided through input
63// byte arrays, each containing data in PEM format.
64// http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx
65func NewManagementAPICertDataWithRetryPolicy(subscriptionId string, cert, key []byte, location string, policy RetryPolicy) (*ManagementAPI, error) {
66 session, err := newX509SessionCertData(subscriptionId, cert, key, location, policy)
67 if err != nil {
68 return nil, err
69 }
70 api := ManagementAPI{session, DefaultPollerInterval, DefaultPollerTimeout}
71 return &api, nil
72}
73
74// NewManagementAPICertData creates an object used to interact with Windows Azure's API.
75// Certificate and private key data are provided through input byte arrays,
76// each containing data in PEM format.
77// http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx
78func NewManagementAPICertData(subscriptionId string, cert, key []byte, location string) (*ManagementAPI, error) {
79 return NewManagementAPICertDataWithRetryPolicy(subscriptionId, cert, key, location, NoRetryPolicy)
80}
81
82// NewManagementAPICertsWithRetryPolicy creates an object used to interact with
83// Windows Azure's API.
84// http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx
85func NewManagementAPICertsWithRetryPolicy(subscriptionId string, certs []tls.Certificate, location string, policy RetryPolicy) (*ManagementAPI, error) {
86 session, err := newX509SessionCerts(subscriptionId, certs, location, policy)
87 if err != nil {
88 return nil, err
89 }
90 api := ManagementAPI{session, DefaultPollerInterval, DefaultPollerTimeout}
91 return &api, nil
92}
93
94// NewManagementAPICerts creates an object used to interact with Windows Azure's API.
95// http://msdn.microsoft.com/en-us/library/windowsazure/ff800682.aspx
96func NewManagementAPICerts(subscriptionId string, certs []tls.Certificate, location string) (*ManagementAPI, error) {
97 return NewManagementAPICertsWithRetryPolicy(subscriptionId, certs, location, NoRetryPolicy)
98}
99
57var operationIDHeaderName = http.CanonicalHeaderKey("x-ms-request-id")100var operationIDHeaderName = http.CanonicalHeaderKey("x-ms-request-id")
58101
59// getOperationID extracts the Windows Azure operation ID from the headers102// getOperationID extracts the Windows Azure operation ID from the headers
60103
=== modified file 'management_base_test.go'
--- management_base_test.go 2014-03-12 03:56:53 +0000
+++ management_base_test.go 2014-09-25 02:19:41 +0000
@@ -4,6 +4,7 @@
4package gwacl4package gwacl
55
6import (6import (
7 "bytes"
7 "encoding/base64"8 "encoding/base64"
8 "encoding/xml"9 "encoding/xml"
9 "errors"10 "errors"
@@ -207,7 +208,7 @@
207 c.Assert(err, IsNil)208 c.Assert(err, IsNil)
208}209}
209210
210var testCert = dedent.Dedent(`211var testKey = []byte(dedent.Dedent(`
211 -----BEGIN PRIVATE KEY-----212 -----BEGIN PRIVATE KEY-----
212 MIIBCgIBADANBgkqhkiG9w0BAQEFAASB9TCB8gIBAAIxAKQGQxP1i0VfCWn4KmMP213 MIIBCgIBADANBgkqhkiG9w0BAQEFAASB9TCB8gIBAAIxAKQGQxP1i0VfCWn4KmMP
213 taUFn8sMBKjP/9vHnUYdZRvvmoJCA1C6arBUDp8s2DNX+QIDAQABAjBLRqhwN4dU214 taUFn8sMBKjP/9vHnUYdZRvvmoJCA1C6arBUDp8s2DNX+QIDAQABAjBLRqhwN4dU
@@ -216,6 +217,8 @@
216 GBW7VXLxbExpgnhb1V97vjQmTfthXQjYAwIYSTEjoFXm4+Bk5xuBh2IidgSeGZaC217 GBW7VXLxbExpgnhb1V97vjQmTfthXQjYAwIYSTEjoFXm4+Bk5xuBh2IidgSeGZaC
217 FFY9AhkAsteo31cyQw2xJ80SWrmsIw+ps7Cvt5W9218 FFY9AhkAsteo31cyQw2xJ80SWrmsIw+ps7Cvt5W9
218 -----END PRIVATE KEY-----219 -----END PRIVATE KEY-----
220 `[1:]))
221var testCert = []byte(dedent.Dedent(`
219 -----BEGIN CERTIFICATE-----222 -----BEGIN CERTIFICATE-----
220 MIIBDzCByqADAgECAgkAgIBb3+lSwzEwDQYJKoZIhvcNAQEFBQAwFTETMBEGA1UE223 MIIBDzCByqADAgECAgkAgIBb3+lSwzEwDQYJKoZIhvcNAQEFBQAwFTETMBEGA1UE
221 AxQKQEhvc3ROYW1lQDAeFw0xMzA3MTkxNjA1NTRaFw0yMzA3MTcxNjA1NTRaMBUx224 AxQKQEhvc3ROYW1lQDAeFw0xMzA3MTkxNjA1NTRaFw0yMzA3MTcxNjA1NTRaMBUx
@@ -224,20 +227,20 @@
224 AAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADMQABKfn08tKfzzqMMD2w227 AAGjDTALMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADMQABKfn08tKfzzqMMD2w
225 PI2fs3bw5bRH8tmGjrsJeEdp9crCBS8I3hKcxCkTTRTowdY=228 PI2fs3bw5bRH8tmGjrsJeEdp9crCBS8I3hKcxCkTTRTowdY=
226 -----END CERTIFICATE-----229 -----END CERTIFICATE-----
227 `[1:])230 `[1:]))
231var testCertKey = bytes.Join([][]byte{testKey, testCert}, []byte{})
228232
229func (suite *managementBaseAPISuite) TestNewManagementAPI(c *C) {233func (suite *managementBaseAPISuite) TestNewManagementAPI(c *C) {
230 subscriptionId := "subscriptionId"234 subscriptionId := "subscriptionId"
231 certDir := c.MkDir()235 certDir := c.MkDir()
232 certFile := certDir + "/cert.pem"236 certFile := certDir + "/cert.pem"
233 err := ioutil.WriteFile(certFile, []byte(testCert), 0600)237 err := ioutil.WriteFile(certFile, testCertKey, 0600)
234 c.Assert(err, IsNil)238 c.Assert(err, IsNil)
235239
236 api, err := NewManagementAPI(subscriptionId, certFile, "West US")240 api, err := NewManagementAPI(subscriptionId, certFile, "West US")
237 c.Assert(err, IsNil)241 c.Assert(err, IsNil)
238242
239 c.Assert(api.session.subscriptionId, DeepEquals, subscriptionId)243 c.Assert(api.session.subscriptionId, DeepEquals, subscriptionId)
240 c.Assert(api.session.certFile, DeepEquals, certFile)
241 c.Assert(api.session.retryPolicy, DeepEquals, NoRetryPolicy)244 c.Assert(api.session.retryPolicy, DeepEquals, NoRetryPolicy)
242}245}
243246
@@ -245,7 +248,7 @@
245 subscriptionId := "subscriptionId"248 subscriptionId := "subscriptionId"
246 certDir := c.MkDir()249 certDir := c.MkDir()
247 certFile := certDir + "/cert.pem"250 certFile := certDir + "/cert.pem"
248 err := ioutil.WriteFile(certFile, []byte(testCert), 0600)251 err := ioutil.WriteFile(certFile, testCertKey, 0600)
249 c.Assert(err, IsNil)252 c.Assert(err, IsNil)
250 retryPolicy := RetryPolicy{NbRetries: 5, HttpStatusCodes: []int{409}, Delay: time.Minute}253 retryPolicy := RetryPolicy{NbRetries: 5, HttpStatusCodes: []int{409}, Delay: time.Minute}
251254
@@ -253,7 +256,28 @@
253 c.Assert(err, IsNil)256 c.Assert(err, IsNil)
254257
255 c.Assert(api.session.subscriptionId, DeepEquals, subscriptionId)258 c.Assert(api.session.subscriptionId, DeepEquals, subscriptionId)
256 c.Assert(api.session.certFile, DeepEquals, certFile)259 c.Assert(api.session.retryPolicy, DeepEquals, retryPolicy)
260 c.Assert(api.GetRetryPolicy(), DeepEquals, retryPolicy)
261}
262
263func (suite *managementBaseAPISuite) TestNewManagementAPICertData(c *C) {
264 subscriptionId := "subscriptionId"
265
266 api, err := NewManagementAPICertData(subscriptionId, testCert, testKey, "West US")
267 c.Assert(err, IsNil)
268
269 c.Assert(api.session.subscriptionId, DeepEquals, subscriptionId)
270 c.Assert(api.session.retryPolicy, DeepEquals, NoRetryPolicy)
271}
272
273func (suite *managementBaseAPISuite) TestNewManagementAPICertDataWithRetryPolicy(c *C) {
274 subscriptionId := "subscriptionId"
275 retryPolicy := RetryPolicy{NbRetries: 5, HttpStatusCodes: []int{409}, Delay: time.Minute}
276
277 api, err := NewManagementAPICertDataWithRetryPolicy(subscriptionId, testCert, testKey, "West US", retryPolicy)
278 c.Assert(err, IsNil)
279
280 c.Assert(api.session.subscriptionId, DeepEquals, subscriptionId)
257 c.Assert(api.session.retryPolicy, DeepEquals, retryPolicy)281 c.Assert(api.session.retryPolicy, DeepEquals, retryPolicy)
258 c.Assert(api.GetRetryPolicy(), DeepEquals, retryPolicy)282 c.Assert(api.GetRetryPolicy(), DeepEquals, retryPolicy)
259}283}
260284
=== modified file 'x509session.go'
--- x509session.go 2014-02-04 08:58:10 +0000
+++ x509session.go 2014-09-25 02:19:41 +0000
@@ -14,7 +14,6 @@
1414
15type x509Session struct {15type x509Session struct {
16 subscriptionId string16 subscriptionId string
17 certFile string
18 client *http.Client17 client *http.Client
19 baseURL *url.URL18 baseURL *url.URL
20 retryPolicy RetryPolicy19 retryPolicy RetryPolicy
@@ -32,13 +31,32 @@
32func newX509Session(subscriptionId, certFile, location string, retryPolicy RetryPolicy) (*x509Session, error) {31func newX509Session(subscriptionId, certFile, location string, retryPolicy RetryPolicy) (*x509Session, error) {
33 certs := []tls.Certificate{}32 certs := []tls.Certificate{}
34 if certFile != "" {33 if certFile != "" {
35 //
36 cert, err := tls.LoadX509KeyPair(certFile, certFile)34 cert, err := tls.LoadX509KeyPair(certFile, certFile)
37 if err != nil {35 if err != nil {
38 return nil, err36 return nil, err
39 }37 }
40 certs = append(certs, cert)38 certs = append(certs, cert)
41 }39 }
40 return newX509SessionCerts(subscriptionId, certs, location, retryPolicy)
41}
42
43// newX509SessionCertData creates and returns a new x509Session based on credentials
44// and X509 certificate byte arrays.
45func newX509SessionCertData(subscriptionId string, cert, key []byte, location string, retryPolicy RetryPolicy) (*x509Session, error) {
46 certs := []tls.Certificate{}
47 if cert != nil && key != nil {
48 cert, err := tls.X509KeyPair(cert, key)
49 if err != nil {
50 return nil, err
51 }
52 certs = append(certs, cert)
53 }
54 return newX509SessionCerts(subscriptionId, certs, location, retryPolicy)
55}
56
57// newX509SessionCerts creates and returns a new x509Session based on credentials
58// and X509 certificate files.
59func newX509SessionCerts(subscriptionId string, certs []tls.Certificate, location string, retryPolicy RetryPolicy) (*x509Session, error) {
42 client := http.Client{60 client := http.Client{
43 Transport: &http.Transport{61 Transport: &http.Transport{
44 TLSClientConfig: &tls.Config{62 TLSClientConfig: &tls.Config{
@@ -66,7 +84,6 @@
6684
67 session := x509Session{85 session := x509Session{
68 subscriptionId: subscriptionId,86 subscriptionId: subscriptionId,
69 certFile: certFile,
70 client: &client,87 client: &client,
71 baseURL: baseURL,88 baseURL: baseURL,
72 retryPolicy: retryPolicy,89 retryPolicy: retryPolicy,

Subscribers

People subscribed via source and target branches

to all changes: