diff options
-rw-r--r-- | src/k8splugin/cmd/main.go | 11 | ||||
-rw-r--r-- | src/k8splugin/go.mod | 1 | ||||
-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, 214 insertions, 1 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 00ee2c8e..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 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----- |