auth
auth/client/client.go
Add kubernetes definitions. Define a replication controller that will spin up authd servers (using Ducky right now--other instances should rename the ducky parts appropriately). Also, my understanding of which labels go where may be shaky, which is probably evidenced by the fact that all of these things share the same lables. _Whatever_. It also hooks the generated pods up to the JWT secret volume, so they can properly read the JWT secret. Also, created a LoadBalancer Service that will route traffic to the pods created by the Replication Controller.
1 package client
3 import (
4 "bytes"
5 "encoding/json"
6 "errors"
7 "io"
8 "net/http"
9 "strings"
10 "time"
12 "code.secondbit.org/auth.hg"
13 "code.secondbit.org/uuid.hg"
14 )
16 var (
17 ErrNilClient = errors.New("nil client wrapper")
18 ErrNilHTTPClient = errors.New("nil client")
19 )
21 type Client struct {
22 client *http.Client
23 address string
24 ID uuid.ID
25 }
27 func New(address string, id uuid.ID) *Client {
28 address = strings.TrimRight(address, "/")
29 return &Client{
30 address: address,
31 client: &http.Client{},
32 ID: id,
33 }
34 }
36 func (c *Client) do(method, url string, request interface{}, scopes []string, subject uuid.ID) (auth.Response, error) {
37 if c == nil {
38 return auth.Response{}, ErrNilClient
39 }
40 if c.client == nil {
41 return auth.Response{}, ErrNilHTTPClient
42 }
43 var response auth.Response
44 if !strings.HasPrefix(url, "http") {
45 url = strings.TrimLeft(url, "/")
46 url = "/" + url
47 url = c.address + url
48 }
49 var body io.Reader
50 if request != nil {
51 data, err := json.Marshal(request)
52 if err != nil {
53 return response, err
54 }
55 body = bytes.NewBuffer(data)
56 }
57 req, err := http.NewRequest(method, url, body)
58 if err != nil {
59 return response, err
60 }
61 req.Header.Set("Ducky-Scope", strings.Join(scopes, " "))
62 req.Header.Set("Ducky-Issuer", c.ID.String())
63 if subject != nil {
64 req.Header.Set("Ducky-Subject", subject.String())
65 }
66 req.Header.Set("Ducky-Expires", time.Now().Add(time.Hour).String())
67 req.Header.Set("Ducky-Issued-At", time.Now().String())
68 req.Header.Set("Ducky-Not-Before", time.Now().Add(-5*time.Minute).String())
69 resp, err := c.client.Do(req)
70 if err != nil {
71 return response, err
72 }
73 defer resp.Body.Close()
74 switch resp.Header.Get("Content-Type") {
75 case "application/json":
76 dec := json.NewDecoder(resp.Body)
77 err = dec.Decode(&response)
78 if err != nil {
79 return response, err
80 }
81 default:
82 dec := json.NewDecoder(resp.Body)
83 err = dec.Decode(&response)
84 if err != nil {
85 return response, err
86 }
87 }
88 return response, nil
89 }
91 func (c *Client) Get(url string, scopes []string, subject uuid.ID) (auth.Response, error) {
92 return c.do("GET", url, nil, scopes, subject)
93 }