Skip to content

Commit

Permalink
Add support for Certificate and SNIs
Browse files Browse the repository at this point in the history
  • Loading branch information
CyExy committed Feb 4, 2018
1 parent a4e5724 commit e6aa1aa
Show file tree
Hide file tree
Showing 21 changed files with 663 additions and 6 deletions.
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ consumers:
upstreams:
- name: "mockbinUpstream"
ensure: "present"
targets:
targets:
- target: "server1.mockbin:3001"
attributes:
weight: 50
Expand All @@ -347,6 +347,36 @@ upstreams:
slots: 100
```

### Certificates & SNIs

*A certificate object represents a public certificate/private key pair for an SSL certificate. These objects are used by Kong to handle SSL/TLS termination for encrypted requests. Certificates are optionally associated with SNI objects to tie a cert/key pair to one or more hostnames.*

[Kong Certificate Object Reference](https://getkong.org/docs/0.11.x/admin-api/#certificate-object)

*An SNI object represents a many-to-one mapping of hostnames to a certificate. That is, a certificate object can have many hostnames associated with it; when Kong receives an SSL request, it uses the SNI field in the Client Hello to lookup the certificate object based on the SNI associated with the certificate.*

[Kong SNI Objects Reference](https://getkong.org/docs/0.11.x/admin-api/#sni-objects)

```yaml
certificates:
- ensure: present
cert: >-
-----BEGIN CERTIFICATE-----
MIIDMjCCAhqgAwIBAgIJAPgRdnOdnX/SMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV
....
key: >-
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAo5BpOQY2AV/1L2QEdSip75rHh3Khs2knNtMLIrP26MHyidtX
....
snis:
- name: example.com
ensure: present
- name: www.example.com
ensure: present
```

> Notice that SNIs are an list of object e.g. `{ name: example.com, ensure: present }` different Kong api itself where it is a list of hostnames


## Migrating from Kong <=0.9 to >=0.10

Expand Down
129 changes: 129 additions & 0 deletions examples/certificates.example.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
certificates example
--------------------

## Config file

```yaml
certificates:
- ensure: present
cert: '-----BEGIN CERTIFICATE-----
MIIDMjCCAhqgAwIBAgIJAPgRdnOdnX/SMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV
BAMTD3d3dy5leGFtcGxlLmNvbTAeFw0xNzExMTkxODUxMDlaFw0yNzExMTcxODUx
MDlaMBoxGDAWBgNVBAMTD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAKOQaTkGNgFf9S9kBHUoqe+ax4dyobNpJzbTCyKz9ujB
8onbV3e8HO5TEQVpIwob3bQ59ZmNkhZxI6jp4ykmXN8gtPOXvWGiSILBcY4p6ttC
RyyVJHSGCKDS5+oUsQA2+ql0ce+ZYl7ePD2kFgzodKCspQaKUe4jvdcEDwsHLmAH
gnFf9oFCCk2McKVH4Vt/YSD6NriTpV0KBCOG260E3vtYWto+djK1AswJCbiTFfnA
a1Vojmu9uX66jfQ/ivZrBFZKHqGtxpBaBa9HV+LaEqehjy2LwQX4fVT4uawDnEM5
zyy+rR+b0h9lTntI7J7pbAm3zywBzaMtQp0boW20C0UCAwEAAaN7MHkwHQYDVR0O
BBYEFJ8KvTYTyM64g0ISOl/HmbM9Y7o/MEoGA1UdIwRDMEGAFJ8KvTYTyM64g0IS
Ol/HmbM9Y7o/oR6kHDAaMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb22CCQD4EXZz
nZ1/0jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCO9jaWppfOI4Qn
R5/NHp1TYxsWei7Xjr0X7wLVgRZGqzhzPKG4eZR7zfXQfg+ufBx1M3/H5DCTv0cm
CgIjatSRxypV9xOzbakAgcSKw/iqjeDZYN/09iVTICONW507X35ONmw6No3tbVLV
tnuGhtcVOyYBtRUpFc9lCWPYpFVMRMMKXnbdXahlt3IPMPx2QY7nWjAo/oC9oZ2A
RMdp9Sav8eCYf8bLR/A+p5DodwvYgOn5sEUXQeYB/w+VsjmYU01NfMR9NxwsDA5b
gXYz44Dl4jhoi/tz/zIOOGA4DlmuJBpMeYtp9SvJ8qhpx3ul/3C2KFOI+/BzdVSl
L5mKwXjd
-----END CERTIFICATE-----'

key: '-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAo5BpOQY2AV/1L2QEdSip75rHh3Khs2knNtMLIrP26MHyidtX
d7wc7lMRBWkjChvdtDn1mY2SFnEjqOnjKSZc3yC085e9YaJIgsFxjinq20JHLJUk
dIYIoNLn6hSxADb6qXRx75liXt48PaQWDOh0oKylBopR7iO91wQPCwcuYAeCcV/2
gUIKTYxwpUfhW39hIPo2uJOlXQoEI4bbrQTe+1ha2j52MrUCzAkJuJMV+cBrVWiO
a725frqN9D+K9msEVkoeoa3GkFoFr0dX4toSp6GPLYvBBfh9VPi5rAOcQznPLL6t
H5vSH2VOe0jsnulsCbfPLAHNoy1CnRuhbbQLRQIDAQABAoIBAAjbgCc7Y99NL/zi
AK/LhPBZxGZcWc9aaWo5oYe+kSdnoVe/zgvI3xQ04V4WpHQesDHbVaZ8GSYn+FNk
Xw3SawMWRVZPqEzKOf0CtsCJGpPHEg2jAfdhbsQux6pQdolZcNeOW8Eq4D3c8Qwx
f5QxXmd5EfK5uNgZjWVAbgQd3nAKwd/a6AHjppTp6ikNJFU4WU3oi/2N7czpOKFi
4tq0Img8VqcKekL4LYUYk8RXi6uk+c5ookB1Q2wh/Fpf9oeLN4kBsxXMt8bEg95D
2Ks5Ekw4yOWnQ8OwfXMWDk46NKMcR7ZYoqfhCk6sc5v6ZFQerJQUBGi2o1Jq2u7Y
5TIl+4ECgYEA1ybYXpGQIIElHbV90RKc6McoF+yeost1ZWyv/646vwWr+pmkgA32
iZnAOvaoAaRJbD5d6gIFdG49lmv36wPvBbzmWBkS9sWujTaEIFHSd9H1R8UxGuud
WqnxrY0cYf6fl4Jrguro6PwAv4gsdCt1HA6d9E85+bHP1lr+R823G2ECgYEAwp44
QdMCvYpLQkbCiLh/UlF2zqZPOQpm2T4NKHxfuH6HKdYyI+ptyx6oP94r/4u7/sYT
nHjCKR7QLGE7qFmnH9Yb2jCd3zFwNBsCoHFhzj6MYzgoV42tpUJl8jRcq351g7hw
Fw2yZG8mW/4lwOhhuVAaUyCngoAs7Jq004bM/mUCgYA/y/PyrsUG7mR8F7n0Ccnf
OFbKKU6sxRnNdloFvbsLs3nYeECP/BPzn1Sh50vQGM/wudmNLwZBDQNUHDXKSUNR
9z5yNxUpeVqV4ulwz/JRtz89BdrWubDSFnxkUuhsolzeRzzr+A4SL89k+9L6q3wx
UqBBtlBhmvke/aJS1kwKYQKBgQCyn7N0vu5Z9u9CQl3UTLoXXMvVuZEnAmQJakl7
akQUupTmEkFs84KYFmhITmtFngQLP9PKHo/eW/incwrlZnvc3ZAsv8h2jRK10ECl
78rcGE6T1nw4d8Hz1zBokCSqBmRnZEYE8r5ULiwf7PDL0L2470tqFqOIRIp3Ezt6
ldPafQKBgQCS2FyQjk6ccJDYQSaERZeVZ7aw/WYU6CMt64WqIcA2sZsHACPg1JuH
rvANyaCjA5QV2cxhZgw9YmwUkP5I6XftplGB81CjmTguGjJ/k5SS8sA2DCHZUna6
vxTZvHMdrkoTodEYmy67Kno3NZotwhRUIdgdQhDN+aG+wjOCxKMTRQ==
-----END RSA PRIVATE KEY-----'
snis:
- ensure: present
name: example.com
- ensure: present
name: www.example.com

```

## Using curl

For illustrative purpose a cURL calls would be the following

### create certificate

```sh
$ curl -i -X POST -H "Content-Type: application/json" \
--url http://localhost:8001/certificates \
--data '{"key":"-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAo5BpOQY2AV/1L2QEdSip75rHh3Khs2knNtMLIrP26MHyidtX d7wc7lMRBWkjChvdtDn1mY2SFnEjqOnjKSZc3yC085e9YaJIgsFxjinq20JHLJUk dIYIoNLn6hSxADb6qXRx75liXt48PaQWDOh0oKylBopR7iO91wQPCwcuYAeCcV/2 gUIKTYxwpUfhW39hIPo2uJOlXQoEI4bbrQTe+1ha2j52MrUCzAkJuJMV+cBrVWiO a725frqN9D+K9msEVkoeoa3GkFoFr0dX4toSp6GPLYvBBfh9VPi5rAOcQznPLL6t H5vSH2VOe0jsnulsCbfPLAHNoy1CnRuhbbQLRQIDAQABAoIBAAjbgCc7Y99NL/zi AK/LhPBZxGZcWc9aaWo5oYe+kSdnoVe/zgvI3xQ04V4WpHQesDHbVaZ8GSYn+FNk Xw3SawMWRVZPqEzKOf0CtsCJGpPHEg2jAfdhbsQux6pQdolZcNeOW8Eq4D3c8Qwx f5QxXmd5EfK5uNgZjWVAbgQd3nAKwd/a6AHjppTp6ikNJFU4WU3oi/2N7czpOKFi 4tq0Img8VqcKekL4LYUYk8RXi6uk+c5ookB1Q2wh/Fpf9oeLN4kBsxXMt8bEg95D 2Ks5Ekw4yOWnQ8OwfXMWDk46NKMcR7ZYoqfhCk6sc5v6ZFQerJQUBGi2o1Jq2u7Y 5TIl+4ECgYEA1ybYXpGQIIElHbV90RKc6McoF+yeost1ZWyv/646vwWr+pmkgA32 iZnAOvaoAaRJbD5d6gIFdG49lmv36wPvBbzmWBkS9sWujTaEIFHSd9H1R8UxGuud WqnxrY0cYf6fl4Jrguro6PwAv4gsdCt1HA6d9E85+bHP1lr+R823G2ECgYEAwp44 QdMCvYpLQkbCiLh/UlF2zqZPOQpm2T4NKHxfuH6HKdYyI+ptyx6oP94r/4u7/sYT nHjCKR7QLGE7qFmnH9Yb2jCd3zFwNBsCoHFhzj6MYzgoV42tpUJl8jRcq351g7hw Fw2yZG8mW/4lwOhhuVAaUyCngoAs7Jq004bM/mUCgYA/y/PyrsUG7mR8F7n0Ccnf OFbKKU6sxRnNdloFvbsLs3nYeECP/BPzn1Sh50vQGM/wudmNLwZBDQNUHDXKSUNR 9z5yNxUpeVqV4ulwz/JRtz89BdrWubDSFnxkUuhsolzeRzzr+A4SL89k+9L6q3wx UqBBtlBhmvke/aJS1kwKYQKBgQCyn7N0vu5Z9u9CQl3UTLoXXMvVuZEnAmQJakl7 akQUupTmEkFs84KYFmhITmtFngQLP9PKHo/eW/incwrlZnvc3ZAsv8h2jRK10ECl 78rcGE6T1nw4d8Hz1zBokCSqBmRnZEYE8r5ULiwf7PDL0L2470tqFqOIRIp3Ezt6 ldPafQKBgQCS2FyQjk6ccJDYQSaERZeVZ7aw/WYU6CMt64WqIcA2sZsHACPg1JuH rvANyaCjA5QV2cxhZgw9YmwUkP5I6XftplGB81CjmTguGjJ/k5SS8sA2DCHZUna6 vxTZvHMdrkoTodEYmy67Kno3NZotwhRUIdgdQhDN+aG+wjOCxKMTRQ== -----END RSA PRIVATE KEY-----","cert":"-----BEGIN CERTIFICATE----- MIIDMjCCAhqgAwIBAgIJAPgRdnOdnX/SMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV BAMTD3d3dy5leGFtcGxlLmNvbTAeFw0xNzExMTkxODUxMDlaFw0yNzExMTcxODUx MDlaMBoxGDAWBgNVBAMTD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBAKOQaTkGNgFf9S9kBHUoqe+ax4dyobNpJzbTCyKz9ujB 8onbV3e8HO5TEQVpIwob3bQ59ZmNkhZxI6jp4ykmXN8gtPOXvWGiSILBcY4p6ttC RyyVJHSGCKDS5+oUsQA2+ql0ce+ZYl7ePD2kFgzodKCspQaKUe4jvdcEDwsHLmAH gnFf9oFCCk2McKVH4Vt/YSD6NriTpV0KBCOG260E3vtYWto+djK1AswJCbiTFfnA a1Vojmu9uX66jfQ/ivZrBFZKHqGtxpBaBa9HV+LaEqehjy2LwQX4fVT4uawDnEM5 zyy+rR+b0h9lTntI7J7pbAm3zywBzaMtQp0boW20C0UCAwEAAaN7MHkwHQYDVR0O BBYEFJ8KvTYTyM64g0ISOl/HmbM9Y7o/MEoGA1UdIwRDMEGAFJ8KvTYTyM64g0IS Ol/HmbM9Y7o/oR6kHDAaMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb22CCQD4EXZz nZ1/0jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCO9jaWppfOI4Qn R5/NHp1TYxsWei7Xjr0X7wLVgRZGqzhzPKG4eZR7zfXQfg+ufBx1M3/H5DCTv0cm CgIjatSRxypV9xOzbakAgcSKw/iqjeDZYN/09iVTICONW507X35ONmw6No3tbVLV tnuGhtcVOyYBtRUpFc9lCWPYpFVMRMMKXnbdXahlt3IPMPx2QY7nWjAo/oC9oZ2A RMdp9Sav8eCYf8bLR/A+p5DodwvYgOn5sEUXQeYB/w+VsjmYU01NfMR9NxwsDA5b gXYz44Dl4jhoi/tz/zIOOGA4DlmuJBpMeYtp9SvJ8qhpx3ul/3C2KFOI+/BzdVSl L5mKwXjd -----END CERTIFICATE-----"}'
```

```
HTTP 201 Created
```

```
{
"created_at": "___created_at___",
"cert": "-----BEGIN CERTIFICATE----- MIIDMjCCAhqgAwIBAgIJAPgRdnOdnX/SMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV BAMTD3d3dy5leGFtcGxlLmNvbTAeFw0xNzExMTkxODUxMDlaFw0yNzExMTcxODUx MDlaMBoxGDAWBgNVBAMTD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBAKOQaTkGNgFf9S9kBHUoqe+ax4dyobNpJzbTCyKz9ujB 8onbV3e8HO5TEQVpIwob3bQ59ZmNkhZxI6jp4ykmXN8gtPOXvWGiSILBcY4p6ttC RyyVJHSGCKDS5+oUsQA2+ql0ce+ZYl7ePD2kFgzodKCspQaKUe4jvdcEDwsHLmAH gnFf9oFCCk2McKVH4Vt/YSD6NriTpV0KBCOG260E3vtYWto+djK1AswJCbiTFfnA a1Vojmu9uX66jfQ/ivZrBFZKHqGtxpBaBa9HV+LaEqehjy2LwQX4fVT4uawDnEM5 zyy+rR+b0h9lTntI7J7pbAm3zywBzaMtQp0boW20C0UCAwEAAaN7MHkwHQYDVR0O BBYEFJ8KvTYTyM64g0ISOl/HmbM9Y7o/MEoGA1UdIwRDMEGAFJ8KvTYTyM64g0IS Ol/HmbM9Y7o/oR6kHDAaMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb22CCQD4EXZz nZ1/0jAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQCO9jaWppfOI4Qn R5/NHp1TYxsWei7Xjr0X7wLVgRZGqzhzPKG4eZR7zfXQfg+ufBx1M3/H5DCTv0cm CgIjatSRxypV9xOzbakAgcSKw/iqjeDZYN/09iVTICONW507X35ONmw6No3tbVLV tnuGhtcVOyYBtRUpFc9lCWPYpFVMRMMKXnbdXahlt3IPMPx2QY7nWjAo/oC9oZ2A RMdp9Sav8eCYf8bLR/A+p5DodwvYgOn5sEUXQeYB/w+VsjmYU01NfMR9NxwsDA5b gXYz44Dl4jhoi/tz/zIOOGA4DlmuJBpMeYtp9SvJ8qhpx3ul/3C2KFOI+/BzdVSl L5mKwXjd -----END CERTIFICATE-----",
"id": "2b47ba9b-761a-492d-9a0c-000000000001",
"key": "-----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEAo5BpOQY2AV/1L2QEdSip75rHh3Khs2knNtMLIrP26MHyidtX d7wc7lMRBWkjChvdtDn1mY2SFnEjqOnjKSZc3yC085e9YaJIgsFxjinq20JHLJUk dIYIoNLn6hSxADb6qXRx75liXt48PaQWDOh0oKylBopR7iO91wQPCwcuYAeCcV/2 gUIKTYxwpUfhW39hIPo2uJOlXQoEI4bbrQTe+1ha2j52MrUCzAkJuJMV+cBrVWiO a725frqN9D+K9msEVkoeoa3GkFoFr0dX4toSp6GPLYvBBfh9VPi5rAOcQznPLL6t H5vSH2VOe0jsnulsCbfPLAHNoy1CnRuhbbQLRQIDAQABAoIBAAjbgCc7Y99NL/zi AK/LhPBZxGZcWc9aaWo5oYe+kSdnoVe/zgvI3xQ04V4WpHQesDHbVaZ8GSYn+FNk Xw3SawMWRVZPqEzKOf0CtsCJGpPHEg2jAfdhbsQux6pQdolZcNeOW8Eq4D3c8Qwx f5QxXmd5EfK5uNgZjWVAbgQd3nAKwd/a6AHjppTp6ikNJFU4WU3oi/2N7czpOKFi 4tq0Img8VqcKekL4LYUYk8RXi6uk+c5ookB1Q2wh/Fpf9oeLN4kBsxXMt8bEg95D 2Ks5Ekw4yOWnQ8OwfXMWDk46NKMcR7ZYoqfhCk6sc5v6ZFQerJQUBGi2o1Jq2u7Y 5TIl+4ECgYEA1ybYXpGQIIElHbV90RKc6McoF+yeost1ZWyv/646vwWr+pmkgA32 iZnAOvaoAaRJbD5d6gIFdG49lmv36wPvBbzmWBkS9sWujTaEIFHSd9H1R8UxGuud WqnxrY0cYf6fl4Jrguro6PwAv4gsdCt1HA6d9E85+bHP1lr+R823G2ECgYEAwp44 QdMCvYpLQkbCiLh/UlF2zqZPOQpm2T4NKHxfuH6HKdYyI+ptyx6oP94r/4u7/sYT nHjCKR7QLGE7qFmnH9Yb2jCd3zFwNBsCoHFhzj6MYzgoV42tpUJl8jRcq351g7hw Fw2yZG8mW/4lwOhhuVAaUyCngoAs7Jq004bM/mUCgYA/y/PyrsUG7mR8F7n0Ccnf OFbKKU6sxRnNdloFvbsLs3nYeECP/BPzn1Sh50vQGM/wudmNLwZBDQNUHDXKSUNR 9z5yNxUpeVqV4ulwz/JRtz89BdrWubDSFnxkUuhsolzeRzzr+A4SL89k+9L6q3wx UqBBtlBhmvke/aJS1kwKYQKBgQCyn7N0vu5Z9u9CQl3UTLoXXMvVuZEnAmQJakl7 akQUupTmEkFs84KYFmhITmtFngQLP9PKHo/eW/incwrlZnvc3ZAsv8h2jRK10ECl 78rcGE6T1nw4d8Hz1zBokCSqBmRnZEYE8r5ULiwf7PDL0L2470tqFqOIRIp3Ezt6 ldPafQKBgQCS2FyQjk6ccJDYQSaERZeVZ7aw/WYU6CMt64WqIcA2sZsHACPg1JuH rvANyaCjA5QV2cxhZgw9YmwUkP5I6XftplGB81CjmTguGjJ/k5SS8sA2DCHZUna6 vxTZvHMdrkoTodEYmy67Kno3NZotwhRUIdgdQhDN+aG+wjOCxKMTRQ== -----END RSA PRIVATE KEY-----",
"snis": []
}
```

### add certificate sni

```sh
$ curl -i -X POST -H "Content-Type: application/json" \
--url http://localhost:8001/snis/ \
--data '{"name":"example.com","ssl_certificate_id":"2b47ba9b-761a-492d-9a0c-000000000001"}'
```

```
HTTP 201 Created
```

```
{
"name": "example.com",
"created_at": "___created_at___",
"ssl_certificate_id": "2b47ba9b-761a-492d-9a0c-000000000001"
}
```

### add certificate sni

```sh
$ curl -i -X POST -H "Content-Type: application/json" \
--url http://localhost:8001/snis/ \
--data '{"name":"www.example.com","ssl_certificate_id":"2b47ba9b-761a-492d-9a0c-000000000001"}'
```

```
HTTP 201 Created
```

```
{
"name": "www.example.com",
"created_at": "___created_at___",
"ssl_certificate_id": "2b47ba9b-761a-492d-9a0c-000000000001"
}
```
25 changes: 25 additions & 0 deletions src/actions/certificates.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export const addCertificate = ({ key, cert }) => ({
type: 'create-certificate',
endpoint: { name: 'certificates' },
method: 'POST',
body: { key, cert },
});

export const removeCertificate = certificateId => ({
type: 'remove-certificate',
endpoint: { name: 'certificate', params: { certificateId } },
method: 'DELETE',
});

export const addCertificateSNI = (ssl_certificate_id, name) => ({
type: 'add-certificate-sni',
endpoint: { name: 'certificate-snis' },
method: 'POST',
body: { name, ssl_certificate_id },
});

export const removeCertificateSNI = sniName => ({
type: 'remove-certificate-sni',
endpoint: { name: 'certificate-sni', params: { sniName } },
method: 'DELETE',
});
1 change: 1 addition & 0 deletions src/adminApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ function createApi({ router, getPaginatedJson, ignoreConsumers }) {
fetchUpstreams: () => getPaginatedJson(router({name: 'upstreams'})),
fetchTargets: (upstreamId) => getPaginatedJson(router({name: 'upstream-targets', params: {upstreamId}})),
fetchTargetsV11Active: (upstreamId) => getPaginatedJson(router({name: 'upstream-targets-active', params: {upstreamId}})),
fetchCertificates: () => getPaginatedJson(router({name: 'certificates'})),

// this is very chatty call and doesn't change so its cached
fetchPluginSchemas: () => {
Expand Down
101 changes: 99 additions & 2 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ import {
updateUpstreamTarget
} from './actions/upstreams'

import {
addCertificate,
removeCertificate,
addCertificateSNI,
removeCertificateSNI,
} from './actions/certificates';

export const consumerAclSchema = {
id: 'group'
};
Expand Down Expand Up @@ -92,6 +99,7 @@ export default async function execute(config, adminApi, logger = () => {}) {
...upstreams(config.upstreams),
...apis(config.apis),
...globalPlugins(config.plugins),
...certificates(config.certificates),
...consumers(splitConsumersConfig.removed),
];

Expand Down Expand Up @@ -139,6 +147,18 @@ export function targets(upstreamName, targets) {
return targets.reduce((actions, target) => [...actions, _target(upstreamName, target)], []);
}

export function certificates(certificates = []) {
return certificates.reduce((actions, cert) => [...actions, _certificate(cert), ...certificatesSNIs(cert, cert.snis)], []);
}

export function certificatesSNIs(certificate, snis) {
if (certificate.ensure === 'removed') {
return [];
}

return snis.reduce((actions, sni) => [...actions, _sni(certificate, sni)], []);
}

function parseResponseContent(content) {
try {
return JSON.parse(content);
Expand Down Expand Up @@ -193,7 +213,7 @@ function _bindWorldState(adminApi) {
}
}

function _createWorld({apis, consumers, plugins, upstreams, _info: { version }}) {
function _createWorld({apis, consumers, plugins, upstreams, certificates, _info: { version }}) {
const world = {
getVersion: () => version,

Expand Down Expand Up @@ -411,7 +431,34 @@ function _createWorld({apis, consumers, plugins, upstreams, _info: { version }})

return targets[0];
}
}
},
getCertificate: ({ key }) => {
const certificate = certificates.find(x => x.key === key);

invariant(certificate, `Unable to find certificate for ${key.substr(1, 50)}`);

return certificate;
},

getCertificateId: certificate => {
return world.getCertificate(certificate)._info.id;
},

hasCertificate: ({ key }) => {
return certificates.some(x => x.key === key);
},

isCertificateUpToDate: certificate => {
const { key, cert } = world.getCertificate(certificate);

return certificate.key == key && certificate.cert == cert;
},

getCertificateSNIs: certificate => {
const { snis } = world.getCertificate(certificate);

return snis;
},
};

return world;
Expand Down Expand Up @@ -763,3 +810,53 @@ function validateUpstreamRequiredAttributes(upstream) {
throw Error(`Upstream name is required: ${JSON.stringify(upstream, null, ' ')}`);
}
}

const _certificate = certificate => {
validateEnsure(certificate.ensure);

return world => {
const identityClue = certificate.key.substr(1, 50);

if (certificate.ensure == 'removed') {
if (world.hasCertificate(certificate)) {
return removeCertificate(world.getCertificateId(certificate));
}

return noop({type: 'noop-certificate', identityClue});
}

if (world.hasCertificate(certificate)) {
if (world.isCertificateUpToDate(certificate)) {
return noop({type: 'noop-certificate', identityClue});
}

return updateCertificate(world.getCertificateId(certificate), certificate);
}

return addCertificate(certificate);
}
}

const _sni = (certificate, sni) => {
validateEnsure(sni.ensure);
invariant(sni.name, 'sni must have a name');

return world => {
const currentSNIs = world.getCertificateSNIs(certificate).map(x => x.name);
const hasSNI = currentSNIs.indexOf(sni.name) !== -1;

if (sni.ensure == 'removed') {
if (hasSNI) {
return removeCertificateSNI(sni.name);
}

return noop({type: 'noop-certificate-sni-removed', sni});
}

if (hasSNI) {
return noop({type: 'noop-certificate-sni', sni});
}

return addCertificateSNI(world.getCertificateId(certificate), sni.name);
};
}
12 changes: 11 additions & 1 deletion src/kongState.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,15 @@ const fetchUpstreamsWithTargets = async ({ version, fetchUpstreams, fetchTargets
);
};

export default async ({fetchApis, fetchPlugins, fetchGlobalPlugins, fetchConsumers, fetchConsumerCredentials, fetchConsumerAcls, fetchUpstreams, fetchTargets, fetchTargetsV11Active, fetchKongVersion}) => {
const fetchCertificatesForVersion = async ({ version, fetchCertificates }) => {
if (semVer.lte(version, '0.10.0')) {
return Promise.resolve([]);
}

return await fetchCertificates();
};

export default async ({fetchApis, fetchPlugins, fetchGlobalPlugins, fetchConsumers, fetchConsumerCredentials, fetchConsumerAcls, fetchUpstreams, fetchTargets, fetchTargetsV11Active, fetchCertificates, fetchKongVersion}) => {
const version = await fetchKongVersion();
const apis = await fetchApis();
const apisWithPlugins = await Promise.all(apis.map(async item => {
Expand Down Expand Up @@ -63,12 +71,14 @@ export default async ({fetchApis, fetchPlugins, fetchGlobalPlugins, fetchConsume
});

const upstreamsWithTargets = await fetchUpstreamsWithTargets({ version, fetchUpstreams, fetchTargets: semVer.gte(version, '0.12.0') ? fetchTargets : fetchTargetsV11Active });
const certificates = await fetchCertificatesForVersion({ version, fetchCertificates });

return {
apis: apisWithPlugins,
consumers: consumersWithCredentialsAndAcls,
plugins: globalPlugins,
upstreams: upstreamsWithTargets,
certificates,
version,
};
};
3 changes: 3 additions & 0 deletions src/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ export const screenLogger = createLogHandler({
'noop-credential': ({ credential, credentialIdName }) => console.log(`- credential ${credential.name.bold} with ${credentialIdName.bold}: ${credential.attributes[credentialIdName].bold} ${'is up to date'.bold.green}`),
'noop-upstream': ({ upstream }) => console.log(`upstream ${upstream.name.bold} ${'is up to date'.bold.green}`),
'noop-target': ({ target }) => console.log(`target ${target.target.bold} ${'is up to date'.bold.green}`),
'noop-certificate': ({ identityClue }) => console.log(`certificate ${identityClue}... ${'is up to date'.bold.green}`),
'noop-certificate-sni': ({ sni }) => console.log(`certificate sni ${sni.name} ${'is up to date'.bold.green}`),
'noop-certificate-sni-removed': ({ sni }) => console.log(`certificate sni ${sni.name} ${'is NOT present'.bold.green}`),

unknown: action => console.log('unknown action', action),
})(message.params),
Expand Down
Loading

0 comments on commit e6aa1aa

Please sign in to comment.