carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package host
2
3import (
4 "net"
5 "net/http"
6 "strings"
7 "time"
8
9 "github.com/carlosframework/platform/internal/edgesfile"
10)
11
12// imdsAddresses is the AWS adapter of AddressSource (region HA spec 2
13// §25): IMDSv2's local-ipv4, public-ipv4, and the VPC's CIDR blocks for
14// the primary interface (network/interfaces/macs/<mac>/vpc-ipv4-cidr-blocks),
15// read on every call. IMDS reports only addresses this instance holds, so
16// once the region's EIP has moved to the load balancer no box reports it
17// (A1-12). A leaf that does not answer 200 is blank.
18type imdsAddresses struct {
19 token func() string
20 leaf func(token, path string) (string, int)
21}
22
23func newIMDSAddresses() imdsAddresses {
24 client := &http.Client{Timeout: 2 * time.Second}
25 return imdsAddresses{
26 token: func() string { return imdsToken(client) },
27 leaf: func(token, path string) (string, int) { return imdsLeaf(client, token, path) },
28 }
29}
30
31func (s imdsAddresses) BoxAddresses() (BoxAddresses, bool) {
32 token := s.token()
33 if token == "" {
34 return BoxAddresses{}, false
35 }
36 // read is a leaf's answer: its value on 200, blank on 404 (IMDS says the
37 // instance has no such leaf: authoritative), and unknown on anything
38 // else, a failed or timed-out request included.
39 unknown := false
40 read := func(path string) string {
41 v, code := s.leaf(token, path)
42 switch code {
43 case http.StatusOK:
44 return v
45 case http.StatusNotFound:
46 default:
47 unknown = true
48 }
49 return ""
50 }
51 out := BoxAddresses{Public: read("/latest/meta-data/public-ipv4")}
52 ip := read("/latest/meta-data/local-ipv4")
53 mac := read("/latest/meta-data/mac")
54 if unknown {
55 return BoxAddresses{}, false
56 }
57 if ip == "" || mac == "" {
58 return out, true
59 }
60 if _, err := net.ParseMAC(mac); err != nil {
61 return out, true
62 }
63 blocks := strings.Fields(read("/latest/meta-data/network/interfaces/macs/" + mac + "/vpc-ipv4-cidr-blocks"))
64 if unknown {
65 return BoxAddresses{}, false
66 }
67 out.Private, out.PrivateCIDR = edgesfile.PrivateAddress(ip, blocks)
68 return out, true
69}
70
71// boxAddressSource is what the edges file publisher reads with region HA
72// on: host.env's settings, then IMDS on EC2. IMDS is asked on every
73// publication that host.env does not fully answer; a failed request makes
74// that publication unknown, and the pass writes nothing and retries.
75func boxAddressSource(getenv func(string) string) AddressSource {
76 return envAddresses{getenv: getenv, provider: newIMDSAddresses()}
77}
78