diff options
author | Kiran Kamineni <kiran.k.kamineni@intel.com> | 2019-04-10 21:53:45 -0700 |
---|---|---|
committer | Kiran Kamineni <kiran.k.kamineni@intel.com> | 2019-04-10 22:00:55 -0700 |
commit | 905a39c8011295ee4b290681f0fda6ca753b7ae3 (patch) | |
tree | 4785df8b773b3083082c6abafb12e81cefaa291f | |
parent | 932322113184862b906f4b82fe83cfcf3403d021 (diff) |
Add option to start https listener
Added support for tls connection for k8splugin.
It will load the certificates from its current folder.
Any installer needs to just put these files in the same
folder as the executable and it will pick them up and start
in https mode.
Issue-ID: MULTICLOUD-570
Change-Id: I505135daa3933b76023c941e7bee54be65fa791f
Signed-off-by: Kiran Kamineni <kiran.k.kamineni@intel.com>
-rw-r--r-- | src/k8splugin/cmd/main.go | 11 | ||||
-rw-r--r-- | src/k8splugin/go.mod | 3 | ||||
-rw-r--r-- | src/k8splugin/internal/auth/auth.go | 107 | ||||
-rw-r--r-- | src/k8splugin/internal/auth/auth_test.go | 47 | ||||
-rw-r--r-- | src/k8splugin/mock_files/mock_certs/auth_test_certificate.pem | 21 | ||||
-rw-r--r-- | src/k8splugin/mock_files/mock_certs/auth_test_key.pem | 28 |
6 files changed, 215 insertions, 2 deletions
diff --git a/src/k8splugin/cmd/main.go b/src/k8splugin/cmd/main.go index e600c0d6..53b6ab17 100644 --- a/src/k8splugin/cmd/main.go +++ b/src/k8splugin/cmd/main.go @@ -24,6 +24,7 @@ import ( "k8splugin/api" utils "k8splugin/internal" + "k8splugin/internal/auth" "github.com/gorilla/handlers" ) @@ -55,5 +56,13 @@ func main() { close(connectionsClose) }() - log.Fatal(httpServer.ListenAndServe()) + tlsConfig, err := auth.GetTLSConfig("ca.cert", "server.cert", "server.key") + if err != nil { + log.Println("Error Getting TLS Configuration. Starting without TLS...") + log.Fatal(httpServer.ListenAndServe()) + } else { + httpServer.TLSConfig = tlsConfig + // empty strings because tlsconfig already has this information + err = httpServer.ListenAndServeTLS("", "") + } } diff --git a/src/k8splugin/go.mod b/src/k8splugin/go.mod index 29a10ecb..531615a6 100644 --- a/src/k8splugin/go.mod +++ b/src/k8splugin/go.mod @@ -67,6 +67,7 @@ require ( github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c // indirect github.com/xdg/stringprep v1.0.0 // indirect go.mongodb.org/mongo-driver v1.0.0 + golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 golang.org/x/net v0.0.0-20181201002055-351d144fa1fc golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890 // indirect golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 // indirect @@ -75,7 +76,7 @@ require ( gopkg.in/square/go-jose.v2 v2.2.2 // indirect gopkg.in/yaml.v2 v2.2.1 k8s.io/api v0.0.0-20181126151915-b503174bad59 - k8s.io/apiextensions-apiserver v0.0.0-20181126155829-0cd23ebeb688 // indirect + k8s.io/apiextensions-apiserver v0.0.0-20181126155829-0cd23ebeb688 k8s.io/apimachinery v0.0.0-20181126123746-eddba98df674 k8s.io/apiserver v0.0.0-20181126153457-92fdef3a232a // indirect k8s.io/cli-runtime v0.0.0-20190107235426-31214e12222d // indirect diff --git a/src/k8splugin/internal/auth/auth.go b/src/k8splugin/internal/auth/auth.go new file mode 100644 index 00000000..3da8f2af --- /dev/null +++ b/src/k8splugin/internal/auth/auth.go @@ -0,0 +1,107 @@ +/* + * Copyright 2018 Intel Corporation, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package auth + +import ( + "crypto/tls" + "crypto/x509" + "encoding/base64" + "encoding/pem" + "io/ioutil" + "log" + + pkgerrors "github.com/pkg/errors" +) + +// GetTLSConfig initializes a tlsConfig using the CA's certificate +// This config is then used to enable the server for mutual TLS +func GetTLSConfig(caCertFile string, certFile string, keyFile string) (*tls.Config, error) { + + // Initialize tlsConfig once + caCert, err := ioutil.ReadFile(caCertFile) + + if err != nil { + return nil, pkgerrors.Wrap(err, "Read CA Cert file") + } + + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + tlsConfig := &tls.Config{ + // Change to RequireAndVerify once we have mandatory certs + ClientAuth: tls.VerifyClientCertIfGiven, + ClientCAs: caCertPool, + MinVersion: tls.VersionTLS12, + } + + certPEMBlk, err := readPEMBlock(certFile) + if err != nil { + return nil, pkgerrors.Wrap(err, "Read Cert File") + } + + keyPEMBlk, err := readPEMBlock(keyFile) + if err != nil { + return nil, pkgerrors.Wrap(err, "Read Key File") + } + + tlsConfig.Certificates = make([]tls.Certificate, 1) + tlsConfig.Certificates[0], err = tls.X509KeyPair(certPEMBlk, keyPEMBlk) + if err != nil { + return nil, pkgerrors.Wrap(err, "Load x509 cert and key") + } + + tlsConfig.BuildNameToCertificate() + return tlsConfig, nil +} + +func readPEMBlock(filename string) ([]byte, error) { + + pemData, err := ioutil.ReadFile(filename) + if err != nil { + return nil, pkgerrors.Wrap(err, "Read PEM File") + } + + pemBlock, rest := pem.Decode(pemData) + if len(rest) > 0 { + log.Println("Pemfile has extra data") + } + + if x509.IsEncryptedPEMBlock(pemBlock) { + password, err := ioutil.ReadFile(filename + ".pass") + if err != nil { + return nil, pkgerrors.Wrap(err, "Read Password File") + } + + pByte, err := base64.StdEncoding.DecodeString(string(password)) + if err != nil { + return nil, pkgerrors.Wrap(err, "Decode PEM Password") + } + + pemData, err = x509.DecryptPEMBlock(pemBlock, pByte) + if err != nil { + return nil, pkgerrors.Wrap(err, "Decrypt PEM Data") + } + var newPEMBlock pem.Block + newPEMBlock.Type = pemBlock.Type + newPEMBlock.Bytes = pemData + // Converting back to PEM from DER data you get from + // DecryptPEMBlock + pemData = pem.EncodeToMemory(&newPEMBlock) + } + + return pemData, nil +} diff --git a/src/k8splugin/internal/auth/auth_test.go b/src/k8splugin/internal/auth/auth_test.go new file mode 100644 index 00000000..49494eee --- /dev/null +++ b/src/k8splugin/internal/auth/auth_test.go @@ -0,0 +1,47 @@ +/* +* Copyright 2018 TechMahindra +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ + +package auth + +import ( + "crypto/tls" + "testing" +) + +//Unit test to varify GetTLSconfig func and varify the tls config min version to be 771 +//Assuming cert file name as auth_test.cert +func TestGetTLSConfig(t *testing.T) { + _, err := GetTLSConfig("filedoesnotexist.cert", "filedoesnotexist.cert", "filedoesnotexist.cert") + if err == nil { + t.Errorf("Test failed, expected error but got none") + } + tlsConfig, err := GetTLSConfig("../../mock_files/mock_certs/auth_test_certificate.pem", + "../../mock_files/mock_certs/auth_test_certificate.pem", + "../../mock_files/mock_certs/auth_test_key.pem") + if err != nil { + t.Fatal("Test Failed as GetTLSConfig returned error: " + err.Error()) + } + expected := tls.VersionTLS12 + actual := tlsConfig.MinVersion + if tlsConfig != nil { + if int(actual) != expected { + t.Errorf("Test Failed due to version mismatch") + } + if tlsConfig == nil { + t.Errorf("Test Failed due to GetTLSConfig returned nil") + } + } +} diff --git a/src/k8splugin/mock_files/mock_certs/auth_test_certificate.pem b/src/k8splugin/mock_files/mock_certs/auth_test_certificate.pem new file mode 100644 index 00000000..42e77491 --- /dev/null +++ b/src/k8splugin/mock_files/mock_certs/auth_test_certificate.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDXTCCAkWgAwIBAgIJAKAHJi8eUs73MA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMTgwNTE1MDQ0MDQwWhcNMTkwNTE1MDQ0MDQwWjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA5PHDk+RRFh5o3Xe2nZuLn0Vo+5BjnHp/ul2NNYSG00Slc8F86gW4xcNA +wm6xC8tYCSangV2lFG3E8H2L7SCEVaM5VDV2GCOpOoMihc+2Qenk/YbHwuYenwjo +OgTK4aCItqjcAJ2DB1KC7AxARxHBDu9Kif+M/pc49so+G9ObQuS8k2vmTTaRYkMK +ZvbTJcWsc0vbNnPhxcG5PVj4unlaREM+yQDm18/glUkkBNnYKMHABRvPnBrDktTT +BQWsqkbQTw7ZuLOrl9rCzVTstZX9wEXarrstIdQJj3KZjbFOp2opND8bjNIjcdVt +iRFnP1nHQYr7EgRqcx/YMJZ+gmCy3wIDAQABo1AwTjAdBgNVHQ4EFgQU9qPNwwIu +kZh41sJqFtnMC2blSYMwHwYDVR0jBBgwFoAU9qPNwwIukZh41sJqFtnMC2blSYMw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEA4+daLY1wE10IMPaOKurG +QBvfYeO/rgNXGeg0TisTIKAfx/We9Hmwo/37Bd2Nk5gxfy/DIJ4lMbrzXjgWITlm +XOrS5QfluwvaEcREtHFtPFa3NZqn2VzKNDFTR+rJj7I5o600NKdcPrGeQ1i/vny2 +K0g68ogw2jfufcuePvZTYGst8RclomPr7ZXxI24kIjcE1MbiViy68sQueTXBEr5s +Th6RsvPfVnLxjR/m/V6VJl31nn4T6hbmKzXCHo/X7aC3I8Isui4bQGKgfAxyBkhE +0T7tP+GgymiEKQ6qJ/1c4HFFSuFRUQjLnK7uJu9jM/HMKoLCPayx6birHZRIMF94 +pg== +-----END CERTIFICATE----- diff --git a/src/k8splugin/mock_files/mock_certs/auth_test_key.pem b/src/k8splugin/mock_files/mock_certs/auth_test_key.pem new file mode 100644 index 00000000..5f01f572 --- /dev/null +++ b/src/k8splugin/mock_files/mock_certs/auth_test_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDk8cOT5FEWHmjd +d7adm4ufRWj7kGOcen+6XY01hIbTRKVzwXzqBbjFw0DCbrELy1gJJqeBXaUUbcTw +fYvtIIRVozlUNXYYI6k6gyKFz7ZB6eT9hsfC5h6fCOg6BMrhoIi2qNwAnYMHUoLs +DEBHEcEO70qJ/4z+lzj2yj4b05tC5LyTa+ZNNpFiQwpm9tMlxaxzS9s2c+HFwbk9 +WPi6eVpEQz7JAObXz+CVSSQE2dgowcAFG8+cGsOS1NMFBayqRtBPDtm4s6uX2sLN +VOy1lf3ARdquuy0h1AmPcpmNsU6naik0PxuM0iNx1W2JEWc/WcdBivsSBGpzH9gw +ln6CYLLfAgMBAAECggEAYB3H2D0QddLKf8AUoNJ+qZ1AV+zkhPtAyIMiF4fN+sBl +HdXrlWxViGFSvM4v8h2qlhzuUfd4qLz042ox5pmyNSnTlbDkJXpDP9dyFO+BOubx +Ribhksd9r5LTvBfq/RKikt0NkAyQx/AyGtuB2NRxUs3PY2QwU2o1dhauQIx0MH5/ +6D8PgQf6+5njKQaKa4e8Kp4kB+KjnALvt6JgYuNJUHWap+nnDbuuVy5dl1bKkAZ+ +qa7CITKWO4kE2EqaCb2asFc2w3538+w72UJZtwQCmOaxtKpRSl9fQXu54N8jIGoZ +1FvEj5x3X6QkglE+iVJYaX3RmiJ3uzZ2LICDr89vEQKBgQD7fquIw4p1idSxz3Cm +5o3Y5kD0CKm61ZaRJWKd+tNlSsxubmV9HROYW6vj2xEPSDvyp1na00pDXxMJQLLc +O5Awd1SaU+d45jnoi70fsEY8X0WH1rDTYfnU+zQBmpbGqX5qTIfpy4yoADiUD1CQ +EBdaSBWiKPx2jFSct58TwDP9YwKBgQDpC64TScZYz7uQq4gAbDso/7TjNwgt/Bw8 +JgLSdx1UdUclh81smTujsouyCFwJSvRjKik8e/Qt0f5patukFbFRINxUGUDhOKbA +7zqeNQbeYaP7Rvw+3z01CU2BTBmB/EWa2xWDam8B9xQvjiHSOrubqkt3sIQJb045 +hzuigdV7VQKBgQD7Gnd0nyCwyMSIIMGuswYv6X4y6i9lr3qdQ4GakOTe/vbsz+cf +K5f0CJuwbnszEgFg/zzVIx/D8rqUA3hSMlp+ObdMO7gi22Q4TsWvTRZjkxBeV7rH +48xJneNIMqyWgIcK5YzSn3y6BTZ4hm3+2UInz09iUJ/6UZTtwNzhIIgIVwKBgQCT +LxRHDE4gIzrT+PHRSonmr/DfnA8nc9WlS2B26lH02IkRs/5Su0iGb6p4y3zNRbCp +vKQElki2c60ZiSqlLCosEfP1jWmDlRMEQVMlPlpTMxmtBr0jPDzc9T4lDhoCFYEk +d3/T2vG3LQRrsHm92+hHPTuioTIS/2BJRxar4RIibQKBgQC8zoayoQ7zfEYxy3Ax +OSao8g85hj0EAJk/VKQP2POgz6KoPay3JE9D7P7OvkebTyv/pijAuTPby4XipCNI +K0JbFC2Kn7RW/ZV23UdnoO9crh2omOh+/52prStWXKoc+/pJe70Af+4rU7FUiI7F +y1mIE9krIoVis6iYsyFEmkP7iw== +-----END PRIVATE KEY----- |