diff --git a/priv/ovsdb/test_ap.cfg b/priv/ovsdb/test_ap.cfg index e8704c9..e0e8ad3 100644 --- a/priv/ovsdb/test_ap.cfg +++ b/priv/ovsdb/test_ap.cfg @@ -5,98 +5,98 @@ {type, <<"EA8300">>}, {tip_host,"10.20.0.112"}, {tip_port,6643}, - {pem, <<"-----BEGIN CERTIFICATE-----\n", - "MIIGWDCCBECgAwIBAgIUQMfsF7t/Gr9jNnjU7wb8Y4aj08AwDQYJKoZIhvcNAQEL\n", - "BQAwgbQxCzAJBgNVBAYTAkNBMRAwDgYDVQQIDAdPbnRhcmlvMQ8wDQYDVQQHDAZP\n", - "dHRhd2ExHzAdBgNVBAoMFkNvbm5lY3RVcyBUZWNobm9sb2dpZXMxGzAZBgNVBAsM\n", - "ElRlc3RpbmcgRGVwYXJ0bWVudDEjMCEGA1UEAwwaVGVzdCBDQSBOb3QgRm9yIERl\n", - "cGxveW1lbnQxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20wHhcNMjAx\n", - "MTA0MTYzNDE1WhcNMjkwMTIxMTYzNDE1WjCBtDELMAkGA1UEBhMCQ0ExEDAOBgNV\n", - "BAgMB09udGFyaW8xDzANBgNVBAcMBk90dGF3YTEfMB0GA1UECgwWQ29ubmVjdFVz\n", - "IFRlY2hub2xvZ2llczEbMBkGA1UECwwSVGVzdGluZyBEZXBhcnRtZW50MSMwIQYD\n", - "VQQDDBpUZXN0IENBIE5vdCBGb3IgRGVwbG95bWVudDEfMB0GCSqGSIb3DQEJARYQ\n", - "dGVzdEBleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\n", - "AN8WmBrKC0BO9lbvhnUxkbXJac14wpr/1DMlu9t6HM+2v4LYtCArJXHv2ChN8IvG\n", - "pA54neei3fEWlP10hTdCvGI1kpmwNaVSBzSKWJmy7KpP9B6OSA2gsC/wN69jpuA9\n", - "s1hCchFwK4hvOjXIEgP6swp7jXOvJZ/8V/4QPns+TvbsCYZKeuI59vZi0TcG4Shq\n", - "G3joz2fYo6d67bgcNDQAuFrNqhcrUjC09ndUUlfL+AqVKooj2sPGUZpGpD4nEspA\n", - "MFwx3vbpPbApk2LS93ZdgzMPj0YY+s4pwzVCgu1LTjkpkHRgwuCLIYkDOjViWiD0\n", - "APEjSlAFj2zxgvSoX7axgtkYhOA7oCi5eNUXZ+D4ktzcCBgF2Vv1JGP6t6pfsqfD\n", - "gHeamFZCo7p5tzEw+lIMgLo04pCHwKawNop9zJE2R82Il/T8HHFobAQxDWC4gcyv\n", - "xbgps3L5ieIxUaM8cpVh1rx4jiANoAucjtYD/QJUN7vvrAO8s0GouIPkG0aqrZgY\n", - "EHxDwAdI1+CGZCZ5ofeiHkkZcXLKQj9d4bFoKca7ragyyhUIbcM/8VGWRSwOx/wX\n", - "eGqV0ZWwSLQxdqIFb+iIe+lnkGE15p37zBOxmYxebRX44CXsrNDDwdSxHKVyjJQB\n", - "S2/Eq6ZnwvRAg8tQPTtJa3evyblpJu9gbSx6isY32r75AgMBAAGjYDBeMB0GA1Ud\n", - "DgQWBBTtfu35+ykmE0o+6kATyeNoHltT5zAfBgNVHSMEGDAWgBTtfu35+ykmE0o+\n", - "6kATyeNoHltT5zAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG\n", - "9w0BAQsFAAOCAgEATKOvh0kA7bfnTwjg/uIwXzYOgxnvnCd3JJ+bMVQCxanxiq0I\n", - "r5p6HgclktXSEXnV/JKLCm+R4gh3xD/NnOK3+qMwJ7wbO5LobzZjBHKKv75oe/kg\n", - "uXvccG0esSf4Vmf1VH9fLDicumeYTQJYH3bVl5v9b/zZQuf0OISptVwZdJDvfR8U\n", - "k6FziNN8kXvWqB6A6ElxG+QzQKm2QKcQzMJGKmnA+kXIMZC5idh8iJZ6kMxRPs8w\n", - "TBL85IwWMRLBPBCMMprWCzSNRiQErqgqV1eXWHx3pTQGTao1ZXnWUpTtoHqoiXQu\n", - "2cyDuMlOcjTDr7exf99ZcYVbgbUpClQFvIX+nuJGvXESn4hv9u4A8C/ZjwDU7n5T\n", - "LqfvXEHWeVC3jAT/6EKkicIcpEzBYR58AQ5qvW+J99mWW4awL8jU4Z++iuf6cGb7\n", - "3hFyUo3A47iGUQnsPTe+tHm32Jn+8BV4s5vc8/sX2CJMRAS1G055brUT1hm4p+NE\n", - "F0yru/HHgndtMD0ssLqiKi0TloVLSbtc8VGr1ryCLPYgcMWNedRnec3viNVV1h5j\n", - "w5W4YUnNE2+aSRUzli5dHh4FYsuBYLPLX2wSFUlXOYDwH4z+T6ZO+7AOFKPDmgiX\n", - "T3HWXngZKiesph2424SNy+qPQvI8YGKNbPgP0PzKSN6+2tMJ+DdA1BDWCpM=\n", - "-----END CERTIFICATE-----\n", - "-----BEGIN CERTIFICATE-----\n", - "MIIFPDCCAySgAwIBAgIBBTANBgkqhkiG9w0BAQsFADCBtDELMAkGA1UEBhMCQ0Ex\n", - "EDAOBgNVBAgMB09udGFyaW8xDzANBgNVBAcMBk90dGF3YTEfMB0GA1UECgwWQ29u\n", - "bmVjdFVzIFRlY2hub2xvZ2llczEbMBkGA1UECwwSVGVzdGluZyBEZXBhcnRtZW50\n", - "MSMwIQYDVQQDDBpUZXN0IENBIE5vdCBGb3IgRGVwbG95bWVudDEfMB0GCSqGSIb3\n", - "DQEJARYQdGVzdEBleGFtcGxlLmNvbTAeFw0yMDExMDQxNjM0MTVaFw0yMzA4MDEx\n", - "NjM0MTVaMGMxCzAJBgNVBAYTAkNBMRAwDgYDVQQIDAdPbnRhcmlvMQ8wDQYDVQQH\n", - "DAZPdHRhd2ExHzAdBgNVBAoMFkNvbm5lY3RVcyBUZWNobm9sb2dpZXMxEDAOBgNV\n", - "BAMMB09wZW5fQVAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDnsnQ\n", - "cRz9A7gvfTvSpcg4fqRDlhKSFmk+gzWtVknZSqGIbDO5JNNzxucmhbzQjiCDk9Q9\n", - "T9BW7yACgRLlHqtx0v7lGtYNOXgD2ZEKOyiDOXkLFz2LvL7cdqS/+YPK1XwEnfVX\n", - "MoIJbKM3GUDtAhoa/v+Hs9G4gogMrSCfdvu4TEjW+GpBA1tbUZL67yJz67Ypjc1Q\n", - "kyDz7bv7cqhZmKGiqVIuJI6UA6wMkkqXTacKoxpEqeCx+BFf/TM7+umW0i3qI5rb\n", - "3cXQn5lApatI536QC7NAmJTcwRuhatAOOmsU+3eu/kqaUWhBk5IyqsS+gXOLgyfT\n", - "Ux63p6RIDydvx3z9AgMBAAGjgagwgaUwHQYDVR0OBBYEFNSXRyUTCK53oanPakBJ\n", - "HptidLPoMB8GA1UdIwQYMBaAFO1+7fn7KSYTSj7qQBPJ42geW1PnMAkGA1UdEwQC\n", - "MAAwCwYDVR0PBAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMCMDMGCWCGSAGG\n", - "+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBDbGllbnQgQ2VydGlmaWNhdGUwDQYJ\n", - "KoZIhvcNAQELBQADggIBAFY5KW9Tja3aYVHWRFbZUD1AUMSvv9elkAK3Z176yWb4\n", - "Hv+pLYmEJ8/ic5X7qbh6UMFCzRoSYz2juEwnQ2MiX55hCErBbGJTzwd0rghivXl8\n", - "kFNqmu3YETkK+tDSsfJx2fMQ8mfC7sI25LND63LWXYUwsyFLKN+ISm92eYTE2Yiq\n", - "FECNd+fBjKu35C4XZ9u0uNtmmobvsa1k19C8tfqqg2UGyWKN60H638uf67O9KAZV\n", - "548W/kr6k82kiGxd/7ZOuBteR5ZN15RSbQtNn1a5+q/ygUs/viOghxJeOAhOi7V4\n", - "XX4t1AMeBt9noUU6fibHb51lxnl9wlDJ7qsqE75uC8ejvtz3T3wpL/JOTUZDFEQf\n", - "+AmhhUYeUhWGZJSMBDzKVeyeAPOhE5gHKP9t1YbM6FjSGRqwz74uW232t2koo5tA\n", - "Oc+SRxn1VcHVuRSMnsbTf9Asf5A/OLg9J43A24D4zJZ5Oli5KA0IGdPARJzbY9IB\n", - "ST5diPPYtUg/Qkjdkk0kInw8PgcUnzYkJ4rEiDc3JxAUzR+kIDlnF3lX5NKks3eM\n", - "3FSRRYLBw7AqQm+4qVokmIQNTBjW/hyiIT0qotpTbqWkKzOHVvtv9nCJU12UldmD\n", - "zPRRNTWyaDxiOoYVpPXbGLLZv+F2wCgusrO7GWvDn12xiZvQoMOqkJMqNQm95ieB\n", - "-----END CERTIFICATE-----\n", - "-----BEGIN RSA PRIVATE KEY-----\n", - "MIIEowIBAAKCAQEAw57J0HEc/QO4L3070qXIOH6kQ5YSkhZpPoM1rVZJ2UqhiGwz\n", - "uSTTc8bnJoW80I4gg5PUPU/QVu8gAoES5R6rcdL+5RrWDTl4A9mRCjsogzl5Cxc9\n", - "i7y+3Hakv/mDytV8BJ31VzKCCWyjNxlA7QIaGv7/h7PRuIKIDK0gn3b7uExI1vhq\n", - "QQNbW1GS+u8ic+u2KY3NUJMg8+27+3KoWZihoqlSLiSOlAOsDJJKl02nCqMaRKng\n", - "sfgRX/0zO/rpltIt6iOa293F0J+ZQKWrSOd+kAuzQJiU3MEboWrQDjprFPt3rv5K\n", - "mlFoQZOSMqrEvoFzi4Mn01Met6ekSA8nb8d8/QIDAQABAoIBAG2a2pjfx84790ck\n", - "dBBisvx0eLUlsOIJjI5qFfk5D8ef+UHm3lQuPgvwtjLvXAu+lpkiixiPT7xl3xmI\n", - "GH4n4Qe1oPvdPXHLcWM20/1XiCt+WEPOkb1p08bS8xxdQWq0kvhDSOPCePmu1QRa\n", - "MfaZ5uaZWbM/HZK0EGaJ2m1+zStFF/qlkoLW0VMKrvgClG9ymJ48+GZaK0WqEKzw\n", - "6+iiHPQKbnu+LNGWb9rz5aAnUnZF5EIVh1twYXWpwROUcuUA2mT1y4bHfoD1qWeG\n", - "Xua8BxakFbjOCdXNFNROGPOre2eR6ztBguSCd4s0McpeZKUJI3WwCCaWnf99oYqT\n", - "+TKIzEECgYEA491VwkGnR9zL534TEVJVJlJJee+pM4sR8zok6fsUqfIVODG6qYcT\n", - "eBCK6scudh6mHiJxyc/BMMKyZl8Tx+E08EtSVn8PRmu2xo8Tv+yaiOyYXf4jJkY3\n", - "5W0DT88M43O8l3F4AmnQsLun86HyD3DPsKGQCeurXwkOQll2AeQwIOsCgYEA28Y6\n", - "tuLZphwN2sPK6dpCu+Vk9m/X2HChLYtqWXbYtEXG1nUE4pkhRguehCYlTtVJNaLg\n", - "PHfbNR/yaH1EyS/X6yWQkQTi/ESIJrVAqyE3VallakCJRNe+H1Pzn3ezgQb+t4uh\n", - "Sgs1c0XPh9HdFFFHgnKuh9QIF998tTNFy3tKn7cCgYBSZ9g84WtyxLoFJQYWTJU4\n", - "v6eM7oxddJzwPoXdDI2DjGX6JZng91WmJS1oDNKTqy/eVAyctIKkdLT56saHkb2I\n", - "bWUAnQDUMd4u3s2AqjuU6yOLUn45uEk8snjxIusBUvjQOBvzm3r6f1MU++tDhEPI\n", - "GBW0UMNwIiFDA4F226RAMwKBgEtFc2qb+4tm5F/e2yqI9H5CLPgyiiy5NprQuxX1\n", - "HHdxxo5A+fFaHQlOhXYhUnnTlwVlyYMsUcm6LV4YOWzmk/8XmJHyqINaPX90aLez\n", - "4q3WHMPtYpZPhfBY4oHlj3dLnAXlLtKbUC0w5clQ2XVR+Tn2aUxgFH2Ir7+n1enB\n", - "Sme1AoGBAMhYrSPiAWJ9upnGLKYF5rrJPlHHLo9BHQyTKXPdUdbH2npIuPcSqLCP\n", - "Mqyy1tZPpmLNwcGTgLtO+V/weGu3UNci73tYQOvCGtVqupLdj61R8Ump6XjMtcmr\n", - "txn9dWnaj7TyTPr0H8KlW5j3tGW/PMTgQNablOf6HXEZM1oGnB04\n", - "-----END RSA PRIVATE KEY-----\n">>} + {ca_certs,<<"-----BEGIN CERTIFICATE-----\n", + "MIIGWDCCBECgAwIBAgIUHyfKT2zg5vNPcIv/XhHFlRjz3sswDQYJKoZIhvcNAQEL\n", + "BQAwgbQxCzAJBgNVBAYTAkNBMRAwDgYDVQQIDAdPbnRhcmlvMQ8wDQYDVQQHDAZP\n", + "dHRhd2ExHzAdBgNVBAoMFkNvbm5lY3RVcyBUZWNobm9sb2dpZXMxGzAZBgNVBAsM\n", + "ElRlc3RpbmcgRGVwYXJ0bWVudDEjMCEGA1UEAwwaVGVzdCBDQSBOb3QgRm9yIERl\n", + "cGxveW1lbnQxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20wHhcNMjAx\n", + "MTA5MDA0MTA1WhcNMjkwMTI2MDA0MTA1WjCBtDELMAkGA1UEBhMCQ0ExEDAOBgNV\n", + "BAgMB09udGFyaW8xDzANBgNVBAcMBk90dGF3YTEfMB0GA1UECgwWQ29ubmVjdFVz\n", + "IFRlY2hub2xvZ2llczEbMBkGA1UECwwSVGVzdGluZyBEZXBhcnRtZW50MSMwIQYD\n", + "VQQDDBpUZXN0IENBIE5vdCBGb3IgRGVwbG95bWVudDEfMB0GCSqGSIb3DQEJARYQ\n", + "dGVzdEBleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\n", + "ANi9KkuXsYAhwirPBroWi8+cSvENhcV+4FKHc0652g4FPKNAOfyQeug5tdo3erAc\n", + "flm/ZDZ61tbq6RSfmDEZfq1IuYkQMg/hNue8r8TPZo5+r3yikhxYYpndPKI1lDPZ\n", + "YYGV3YEofK5REpl3vUEgKchtuIxEAb8TPy4swCIuEcOoKzN1wJcVisCkdA76kbKb\n", + "rNL9Wvm7DH1znT6xSgTeFmUHkwKt7Utir3jG0fF9HcnVOfvKB6E6JqQTCUDTTLx9\n", + "tgXfvntTel+H0/xwxsvZOWSSmGdfcLYzUxh38cP2OSYDIQemXWSEDGCXUkcXLD/e\n", + "aUlkmlGRojHomlSvZSAX3Y+hqLeeJOHwx5sU2JVAVTWXPrgWwcIEt0nOV+Ssj2tX\n", + "ia/cPxLDy+5T4Eqvu0hkl+YXg7o5Et6s+4c2OGLMTGWD1jNgCLKuhUBdPD2ss7Wv\n", + "qNWTXUhV870/Um2PrzhoF1WP/9YHRjnD4tG0OGx9zceuXlS2OBYnD3pmgVrJgRBG\n", + "8iEUBCYORVMx3aP1uiSRHjqu8spOKT1wCPqz8P9Vb+QTguUdhfBGCtRL6pCTu46J\n", + "q4xloyDy19mV6y5QUiCi6959I9EiKgj8IlpHZ/m8R5B7d976bfRf/crM85vbwdhw\n", + "s36sJ44VyspEGNyVLgDyLgtRD8wQxBka0q4zCCX7wWF3AgMBAAGjYDBeMB0GA1Ud\n", + "DgQWBBQ5sX4Sn99xQgh2CllULyBXIHflhzAfBgNVHSMEGDAWgBQ5sX4Sn99xQgh2\n", + "CllULyBXIHflhzAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG\n", + "9w0BAQsFAAOCAgEAnagGdt8deMaxzJZxYRenu4y0JyOIb/Fpa83drdaxBBfDYEjN\n", + "jr2WG52m69MRjCIEZbBfVPfkpCq8ciZSxbzLIBmOd0zUVo6v76oXJPjErmFxuqKN\n", + "mVbtj4+uJxcqjV5gWZ2hgOxKMJRc1aPPX07iwwogb8FLm3BUnM/1epPdwr9m4Al5\n", + "R/rbAiS8vHos3JCht2fEwoVWkMbzyidJrpusHvVLXq2M7d3kpJADQk7g3Mg5yjG9\n", + "2QWegKBI0S7Lsn4/7glfPe8Q+PYZOew42oAoMwIr88i3sTowpCdvDNozFvkizxdJ\n", + "/hcpNsOYPyJFCg5MwROw7/QlQTdar7dnvoaagjKPymfJNl4goGVkz6OzjZUp4ZpC\n", + "/TNSnRcUK/k/M5BZCoh+fFhLd6UMv8wzCrPtN9fPr3NBetWzH4OAU7jIHp+PmZyr\n", + "5CzjNpcMs4dfAaBOuT8ZBQpASktYKQSkHeomhaKxFGnt6IB8oHuouQK+4vglXaUK\n", + "szclm6isIL3SW/5CV90uD1ZFmVm5iMjgmathKyDfU2fv3DiF24etilv6hsLw+g+X\n", + "LqyaOwHHgb++giSRlSbAbba8hf1Esal0iPF4JblvcfwvJ7eqKDXpESaDUSV8D8w+\n", + "mhEPYay1Tk5o/13/cVFuJihWluAie6f1irZY2e16MS5Ld8ftpS1cSN6mvDE=\n", + "-----END CERTIFICATE-----\n">>}, + {client_cert,<<"-----BEGIN CERTIFICATE-----\n", + "MIIFPDCCAySgAwIBAgIBBTANBgkqhkiG9w0BAQsFADCBtDELMAkGA1UEBhMCQ0Ex\n", + "EDAOBgNVBAgMB09udGFyaW8xDzANBgNVBAcMBk90dGF3YTEfMB0GA1UECgwWQ29u\n", + "bmVjdFVzIFRlY2hub2xvZ2llczEbMBkGA1UECwwSVGVzdGluZyBEZXBhcnRtZW50\n", + "MSMwIQYDVQQDDBpUZXN0IENBIE5vdCBGb3IgRGVwbG95bWVudDEfMB0GCSqGSIb3\n", + "DQEJARYQdGVzdEBleGFtcGxlLmNvbTAeFw0yMDExMDkwMDQxMDZaFw0yMzA4MDYw\n", + "MDQxMDZaMGMxCzAJBgNVBAYTAkNBMRAwDgYDVQQIDAdPbnRhcmlvMQ8wDQYDVQQH\n", + "DAZPdHRhd2ExHzAdBgNVBAoMFkNvbm5lY3RVcyBUZWNobm9sb2dpZXMxEDAOBgNV\n", + "BAMMB09wZW5fQVAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6gnLq\n", + "K4g+rMVWcTpFR1KNboT7guf738EuYWxB9KrYkS6tt67yd7Pv/AJ+Fo33iMv3JPOm\n", + "RZWWDDNuAnRrvWSqaomRpetB9RwbBApLmriEXwJD12Zoa/Y0AyvYR1WAq++iaFk7\n", + "mVzhELDnfslS/FEJlgZRw9429Fr6EEDUu0S3AwsS3tB63MtfOaESM03U+WyAk6ws\n", + "yDjjgtvWsqwSUzYvZLTMA7N2FCW+hwXYQvr1rSrnKpG8BdW0uiJEN7DDUTsOkEDl\n", + "Vq4BTvQJYKGmJq2dLNgea3eynPpzr3AtgETNvxXvWNC2a40smg+ORcGjEFQf+P3Z\n", + "9Eot1ZOWLL8MQnHbAgMBAAGjgagwgaUwHQYDVR0OBBYEFHaoZFWVXkmZYdg8xqkE\n", + "Nc41EaOmMB8GA1UdIwQYMBaAFDmxfhKf33FCCHYKWVQvIFcgd+WHMAkGA1UdEwQC\n", + "MAAwCwYDVR0PBAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMCMDMGCWCGSAGG\n", + "+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBDbGllbnQgQ2VydGlmaWNhdGUwDQYJ\n", + "KoZIhvcNAQELBQADggIBAI8+NpRM4x9i2JY0Ui3RzQTLoboiVmlDqrLeYC8Bt3UL\n", + "kbEAOPK/JDt5kAf6PpnpCn+s3l8db1ihBJ2rtNu/3Ayr4R957U6m0jc60DbuMEDM\n", + "ICIRho/+ez30S99E0Q3MTVAXAR0D+9kTQ7kJMPRht2Pka0Ep2YKPvpoLDAhlhvTz\n", + "pu129wpTKpep32kxQhUCzHp96SEjK2VVR7jMWul0uyWPL1T1gIHRpVO0eFJEYNmz\n", + "00f1/gZrvMCjnAqm31perXw6gBHHf8Ukoq/HYOo7MGnLfYOBnO2wGmfMlayWLIao\n", + "QScGYuUqBWy8NlXi+bcI1R44dQlHrHmwgI2Fb1EHl3ayFD1ooiUbvpZju3bR+OrK\n", + "XKO6P6RIiCUP1HfGdvug8aPY2D4bzQiz3eeLSTfD5oU+k37D+DJrgmrbb8+sOufA\n", + "iX91ywP2SH6Z5QucOIPaFH+4WZVN7NeV+7zKEFMmWPnXqkAQLwfz1yiL3riSce0I\n", + "DCLDnQzTgt0yv42OfKWkNrq80olIGZMbW3+GQrbgVuY0rUA/T0iRerT5wm10WJtE\n", + "g92AXxSKr46M3It7qZvnaoqtH3Y6cu0mxv1bDEH5rtOyGo5vwFD+TBUR10vY7vTS\n", + "cxU9eR3Fu0t9hxyokVATeyXS4Cx7BTUSYZfN16vGD2N5SU82jX55DXWwigZVAEF4\n", + "-----END CERTIFICATE-----\n", + "-----BEGIN RSA PRIVATE KEY-----\n", + "MIIEpAIBAAKCAQEAuoJy6iuIPqzFVnE6RUdSjW6E+4Ln+9/BLmFsQfSq2JEurbeu\n", + "8nez7/wCfhaN94jL9yTzpkWVlgwzbgJ0a71kqmqJkaXrQfUcGwQKS5q4hF8CQ9dm\n", + "aGv2NAMr2EdVgKvvomhZO5lc4RCw537JUvxRCZYGUcPeNvRa+hBA1LtEtwMLEt7Q\n", + "etzLXzmhEjNN1PlsgJOsLMg444Lb1rKsElM2L2S0zAOzdhQlvocF2EL69a0q5yqR\n", + "vAXVtLoiRDeww1E7DpBA5VauAU70CWChpiatnSzYHmt3spz6c69wLYBEzb8V71jQ\n", + "tmuNLJoPjkXBoxBUH/j92fRKLdWTliy/DEJx2wIDAQABAoIBAQCLO+lH0bnDeD1V\n", + "m++xWl5RgSk7je1bRh40XrxvvJRyWmfrfc3X6u7kgFDoCjRvj6sc1HQkM5xJSNB4\n", + "FtMMv3XQFvqeRawMMEyMCocZC+clwruxI7OqzrYc/CUWL6KwDSs3Jgk/ie0hg9Fc\n", + "8HShRAXHTz1mev+ALQlh1xJe/XJ94DpXWr6f2GRSfWd2T7td7Sb+2mMXcGhXDH0C\n", + "usU1apWgzboVJeBzWcYAUrRqnZsS+M0jNRZGBvQe8tDWHvmSZ155ePywNgDrlJGW\n", + "bPCDBLrCb1immnAFxQ0vKmVzq0910FRV5+mouFzOWRRcIOuTybEJkZU74BGxMuuh\n", + "lynXt9pJAoGBAPUBK7rtto/PA8sIa8AXWZ3TeVaA8xCVUYa6S624saIGvdUu4N3T\n", + "Zyd8189M7NdduYFvI3F7H1XJ6lhaQ4fdL1jouJC5YmbjYXr/TjxPhIqpEOF8qLrS\n", + "zfk+Walc9sbngXqHkqtoUBM3W6YZcEnaU92lpi1DuK0qAKRdC/5hdWfdAoGBAMLh\n", + "PFaFLMhq5hZ7r0woittYEqCiBjqd5ncvEAOY61ilxlT1XzWNGzFosxDHmASP044H\n", + "kzU64b9vX0PU2MpIbi3Y4sEKTOZiyOWSZYkM6VITmmP9yhdmj45BIvSSjIVO1Ywt\n", + "dN3KC096EkWo5qcpI2nC8S1qCZ/Sy3mZYX32w0EXAoGBAIOulWpqyWyRv2AoroEY\n", + "C7qgJt8vf3SyTJc1GefNFOwY437pK0MOlKrMltF8bu9yGHpQ2aPsoPLjC2lhWlpz\n", + "rzcCHfDrMtBJ9eK9xbb0pjBAnioTbjy7gKktsdMtfBV76EOLCnHGJwOtBT1I/uky\n", + "x1Ch76b0dxXbNW0h9YhLqWahAoGALmijDNukIYpLhvknctSI1Nlxfi13nEf0FVfw\n", + "0Vp+WVsJEzxn0wHqguazFgDiM9vofn9RUDDYh9VG84lhozKCgoqO3XfNfmPyAbHO\n", + "Wkfn3HLspnlOwinbb/4VC/dGXYy7kClXFmZCMUgZx9sEKrTCSTJyauVAq33wlOGw\n", + "9OVp9DsCgYAY7oWw5n1KEzcyh1pVsBZIQak9O1JFKxwhH80bEzNTEq35Y04ZKIty\n", + "OSo+gjta+0PbPX6szjOt+glhlyszE2jo++c98BY9MTlr7jJKG+TOGGL95K21OQyA\n", + "6HbOrJtDLkcCIkRtjpISOqExR0fh0h1lmXad8lFkOIJV3lemPYc0Vw==\n", + "-----END RSA PRIVATE KEY-----\n">>} ] }. diff --git a/src/ovsdb_ap.erl b/src/ovsdb_ap.erl index 7fb95a1..4a21df5 100644 --- a/src/ovsdb_ap.erl +++ b/src/ovsdb_ap.erl @@ -21,6 +21,9 @@ -export([launch/2]). -export([start_ap/1,stop_ap/1,pause_ap/1,cancel_ap/1]). +%% comm API +-export([rpc_cmd/2]). + %% gen_server callbacks -export([init/1, handle_cast/2, handle_call/3, handle_info/2, terminate/2, code_change/3]). @@ -91,6 +94,17 @@ cancel_ap (Node) -> +%%%============================================================================ +%%% Comm module API +%%%============================================================================ + + +-spec rpc_cmd (Node :: pid(), Rpc :: term()) -> ok | invalid. + +rpc_cmd (Node,Rpc) -> + gen_server:call(Node,{exec_rpc,Rpc}). + + %%%============================================================================ %%% GEN_SERVER callbacks @@ -169,6 +183,22 @@ handle_cast (R,State) -> Reason :: term(), NewState :: #ap_state{}. +handle_call ({exec_rpc, RPC}, _From, State) when is_map(RPC) andalso + is_map_key(<<"method">>,RPC) andalso + is_map_key(<<"id">>,RPC) -> + io:format("RPC request: ~s (~B)~n",[maps:get(<<"method">>,RPC),maps:get(<<"id">>,RPC)]), + {reply,ok,State}; + +handle_call ({exec_rpc, RPC}, _From, State) when is_map(RPC) andalso + is_map_key(<<"result">>,RPC) andalso + is_map_key(<<"id">>,RPC) -> + io:format("RPC response to request: (~B)~n",[maps:get(<<"id">>,RPC)]), + {reply,ok,State}; + +handle_call ({exec_rpc, RPC}, _From, State) -> + io:format("invalid RPC: ~p~n",[RPC]), + {reply,invalid, State}; + handle_call (Request, From, State) -> ?L_E(?DBGSTR("got unknow request ~p from ~p",[Request,From])), @@ -268,7 +298,8 @@ startup_ap (#ap_state{status=init, config=Cfg, sim_manager=Man}=State) -> Opts = [ {host, ovsdb_ap_config:tip(host,NewCfg)}, {port, ovsdb_ap_config:tip(port,NewCfg)}, - {certs, ovsdb_ap_config:pem(NewCfg)} + {ca, ovsdb_ap_config:ca_certs(NewCfg)}, + {cert, ovsdb_ap_config:client_cert(NewCfg)} ], {ok, Comm} = ovsdb_ap_comm:start_link(Opts), set_status(ready,State#ap_state{config=NewCfg, comm=Comm}). diff --git a/src/ovsdb_ap_comm.erl b/src/ovsdb_ap_comm.erl index a90d5c3..f8e63a4 100644 --- a/src/ovsdb_ap_comm.erl +++ b/src/ovsdb_ap_comm.erl @@ -16,15 +16,18 @@ %% types and specifications -record (c_state, { - socket :: gen_tcp:socket(), - ap :: pid() + socket :: ssl:sslsocket(), + ap :: pid(), + status :: active | idle, + rxb = <<"">> :: binary() }). -type options() :: [ {host, string()} | % tip controller host name {port, integer()} | % port to connect - {certs, binary()} % in memory PEM file of all certs (CA,Cert, Key .. in that order) + {ca, binary()} | % in memory PEM file of the server CA chain + {cert, binary()} % ]. @@ -57,13 +60,13 @@ start_link (Options) -> create_comm (Opts, AP) -> H = proplists:get_value(host,Opts), P = proplists:get_value(port,Opts), - C = proplists:get_value(certs,Opts), - [{'Certificate',CA,not_encrypted}, - {'Certificate',Cert,not_encrypted}, - {KeyType,Key,not_encrypted}] = public_key:pem_decode(C), + CAs = [X || {'Certificate',X,not_encrypted} <- public_key:pem_decode(proplists:get_value(ca,Opts))], + [{'Certificate',Cert,not_encrypted}, + {KeyType,Key,not_encrypted}] = public_key:pem_decode(proplists:get_value(cert,Opts)), State = #c_state{ - socket = connect_to_server(H,P,CA,Cert,{KeyType,Key}), - ap = AP + socket = connect_to_server(H,P,CAs,Cert,{KeyType,Key}), + ap = AP, + status = active }, comm_loop(State). @@ -72,29 +75,53 @@ create_comm (Opts, AP) -> -spec comm_loop (State :: #c_state{}) -> ok. -comm_loop (_State) -> - %% @TODO: proper socket handling ... - io:format("connected ... loop ... exit"), - ok. +comm_loop (#c_state{socket=S, rxb=Rx, ap=AP}=State) -> + receive + {ssl, S, Data} -> + Buffer = process_rx_data(<>,AP), + ok = ssl:setopts(S,[{active,once}]), + comm_loop(State#c_state{status=active, rxb=Buffer}); + + {ssl_closed, S} -> + ?L_I(?DBGSTR("socket closed by server")), + ok; + + {ssl_error, S, Reason} -> + ?L_E(?DBGSTR("socket error ~p",[Reason])), + ssl:close(S); + + {send, AP, Data} -> + ToSend = jiffy:encode(Data), + ok = ssl:send(S,ToSend), + comm_loop(State#c_state{status=active}); + + {down, AP} -> + ssl:close(S) + + after + 10000 -> + comm_loop(State#c_state{status=idle}) + end. --spec connect_to_server (Host, Port, CA, Cert, Key) -> Socket when +-spec connect_to_server (Host, Port, CAs, Cert, Key) -> Socket when Host :: string(), %% host name to connect to (can be IP address in string format) Port :: integer(), %% port to connect to - CA :: public_key:der_encoded(), %% server certificate + CAs:: [public_key:der_encoded()], %% server certificate Cert :: public_key:der_encoded(), %% client certificate Key :: {atom(),public_key:der_encoded()}, %% private key for client cert - Socket :: gen_tcp:socket(). + Socket :: ssl:sslsocket(). -connect_to_server (Host, Port, CA, Cert, Key) -> - Opts = [{cacerts, [CA]}, +connect_to_server (Host, Port, CAs, Cert, Key) -> + Opts = [{cacerts, CAs}, {cert,Cert}, {key,Key}, {versions, ['tlsv1.2','tlsv1.3']}, {session_tickets,auto}, - {mode,binary}], + {mode,binary}, + {active,once}], case ssl:connect(Host, Port, Opts) of {ok, Socket} -> Socket; {error, Reason} -> @@ -103,3 +130,23 @@ connect_to_server (Host, Port, CA, Cert, Key) -> end. + + +%--------process_rx_data/2---------------process data in buffer and ensures only valid decoded JSON is sent to AP + +-spec process_rx_data (Data :: binary(), AP :: pid()) -> Buffer :: binary(). + +process_rx_data (Data, AP) -> + try jiffy:decode(Data,[return_maps,copy_strings,return_trailer]) of + {has_trailer,Map,Tail} -> + ovasd_ap:rpc_cmd(AP,Map), + iolist_to_binary(Tail); + Map -> + ovasd_ap:rpc_cmd(AP,Map), + <<"">> + catch + error:{_,truncated_json} -> + Data; + _:_ -> + <<"">> + end. diff --git a/src/ovsdb_ap_config.erl b/src/ovsdb_ap_config.erl index aec3c5d..30d7e22 100644 --- a/src/ovsdb_ap_config.erl +++ b/src/ovsdb_ap_config.erl @@ -20,7 +20,8 @@ type = <<"">> :: binary(), % device type e.g. EA8300 tip_host = "" :: string(), % host of tip controller tip_port = 0 :: integer(), % port at tip controller - pem = <<"">> :: binary() % pem file (in memory) of the certificates to use + ca_certs = <<"">> :: binary(), % pem file (in memory) of the server certificate chain + client_cert = <<"">> :: binary() % client certificate + private key in pem format }). -opaque cfg() :: #cfg{}. @@ -30,7 +31,7 @@ -export([new/1,configure/2]). --export ([id/1,tip/2,pem/1]). +-export ([id/1,tip/2,ca_certs/1,client_cert/1]). %%------------------------------------------------------------------------------ @@ -56,29 +57,25 @@ configure (_Manager,Config) -> type = proplists:get_value(type,APC), tip_host = proplists:get_value(tip_host,APC), tip_port = proplists:get_value(tip_port,APC), - pem = proplists:get_value(pem,APC) + ca_certs = proplists:get_value(ca_certs,APC), + client_cert = proplists:get_value(client_cert,APC) }. %%------------------------------------------------------------------------------ %% accessor API - - - -spec id (Config :: cfg()) -> Id :: string(). - id (Cfg) -> Cfg#cfg.id. - -spec tip (Part :: host | port, Config :: cfg()) -> string() | integer(). - tip (host,Cfg) -> Cfg#cfg.tip_host; tip (port,Cfg) -> Cfg#cfg.tip_port. +-spec ca_certs (Config :: cfg()) -> binary(). +ca_certs (Cfg) -> Cfg#cfg.ca_certs. --spec pem (Config :: cfg()) -> binary(). - -pem (Cfg) -> Cfg#cfg.pem. +-spec client_cert (Config :: cfg()) -> binary(). +client_cert (Cfg) -> Cfg#cfg.client_cert.