You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by cs...@apache.org on 2017/11/10 17:01:07 UTC
[incubator-openwhisk] branch master updated: Add the support of
certificate checking for secure mode (#2864)
This is an automated email from the ASF dual-hosted git repository.
csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git
The following commit(s) were added to refs/heads/master by this push:
new 07b9b44 Add the support of certificate checking for secure mode (#2864)
07b9b44 is described below
commit 07b9b44cd9e920f796c0cc24dbd506ed62d09f6c
Author: Vincent <sh...@us.ibm.com>
AuthorDate: Fri Nov 10 12:01:04 2017 -0500
Add the support of certificate checking for secure mode (#2864)
Closes: #2863
---
.../src/test/scala/system/basic/WskSdkTests.scala | 55 +++++++++
.../scala/whisk/core/cli/test/WskConfigTests.scala | 132 +++++++++++++++++++++
tools/cli/go-whisk/whisk/client.go | 82 +++++++++----
tools/cli/go-whisk/whisk/info.go | 4 +
tools/cli/go-whisk/whisk/sdk.go | 5 +-
.../cli/go-whisk/wski18n/resources/en_US.all.json | 12 ++
6 files changed, 267 insertions(+), 23 deletions(-)
diff --git a/tests/src/test/scala/system/basic/WskSdkTests.scala b/tests/src/test/scala/system/basic/WskSdkTests.scala
index 021e8ca..b36c823 100644
--- a/tests/src/test/scala/system/basic/WskSdkTests.scala
+++ b/tests/src/test/scala/system/basic/WskSdkTests.scala
@@ -18,6 +18,8 @@
package system.basic
import java.io.File
+import java.io.BufferedWriter
+import java.io.FileWriter
import org.apache.commons.io.FileUtils
import org.junit.runner.RunWith
@@ -120,4 +122,57 @@ class WskSdkTests extends TestHelpers with WskTestHelpers {
val stdout = wsk.cli(Seq("sdk", "install", "bashauto", "--stdout")).stdout
stdout should include(msg)
}
+
+ def verifyMissingSecurityFile(config: String, fileName: String, expectedErrorMessage: String) = {
+ val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+ val securityFile = File.createTempFile(fileName, ".pem")
+ try {
+ val writer = new BufferedWriter(new FileWriter(tmpwskprops))
+ writer.write(s"$config=${securityFile.getAbsolutePath()}\n")
+ writer.close()
+ val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+ val stderr = wsk
+ .cli(
+ Seq("sdk", "install", "docker", "--apihost", wskprops.apihost, "--apiversion", wskprops.apiversion),
+ env = env,
+ expectedExitCode = ERROR_EXIT)
+ .stderr
+ stderr should include regex (expectedErrorMessage)
+ } finally {
+ tmpwskprops.delete()
+ securityFile.delete()
+ }
+ }
+
+ it should "return configure the missing Key file" in {
+ verifyMissingSecurityFile("CERT", "cert", "The Key file is not configured. Please configure the missing Key file.")
+ }
+
+ it should "return configure the missing Cert file" in {
+ verifyMissingSecurityFile("KEY", "key", "The Cert file is not configured. Please configure the missing Cert file.")
+ }
+
+ it should "return unable to load the X509 key pair with both Cert and Key files missing" in {
+ val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+ val certFile = File.createTempFile("cert", ".pem")
+ val keyFile = File.createTempFile("key", ".pem")
+ try {
+ val writer = new BufferedWriter(new FileWriter(tmpwskprops))
+ writer.write(s"CERT=${certFile.getAbsolutePath()}\n")
+ writer.write(s"KEY=${keyFile.getAbsolutePath()}\n")
+ writer.close()
+ val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+ val stderr = wsk
+ .cli(
+ Seq("sdk", "install", "docker", "--apihost", wskprops.apihost, "--apiversion", wskprops.apiversion),
+ env = env,
+ expectedExitCode = ERROR_EXIT)
+ .stderr
+ stderr should include regex ("""Unable to load the X509 key pair due to the following reason""")
+ } finally {
+ tmpwskprops.delete()
+ certFile.delete()
+ keyFile.delete()
+ }
+ }
}
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala
index e4e14e9..220953b 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala
@@ -279,6 +279,72 @@ class WskConfigTests extends TestHelpers with WskTestHelpers {
}
}
+ it should "return configure the missing Cert file" in {
+ val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+ val keyFile = File.createTempFile("key", ".pem")
+ try {
+ val writer = new BufferedWriter(new FileWriter(tmpwskprops))
+ writer.write(s"KEY=${keyFile.getAbsolutePath()}\n")
+ writer.close()
+ val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+ val stderr = wsk
+ .cli(
+ Seq("property", "get", "--apibuild", "--apihost", wskprops.apihost, "--apiversion", wskprops.apiversion),
+ env = env,
+ expectedExitCode = ERROR_EXIT)
+ .stderr
+ stderr should include regex ("""The Cert file is not configured. Please configure the missing Cert file.""")
+ } finally {
+ tmpwskprops.delete()
+ keyFile.delete()
+ }
+ }
+
+ it should "return configure the missing Key file" in {
+ val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+ val certFile = File.createTempFile("cert", ".pem")
+ try {
+ val writer = new BufferedWriter(new FileWriter(tmpwskprops))
+ writer.write(s"CERT=${certFile.getAbsolutePath()}\n")
+ writer.close()
+ val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+ val stderr = wsk
+ .cli(
+ Seq("property", "get", "--apibuild", "--apihost", wskprops.apihost, "--apiversion", wskprops.apiversion),
+ env = env,
+ expectedExitCode = ERROR_EXIT)
+ .stderr
+ stderr should include regex ("""The Key file is not configured. Please configure the missing Key file.""")
+ } finally {
+ tmpwskprops.delete()
+ certFile.delete()
+ }
+ }
+
+ it should "return unable to load the X509 key pair with both Cert and Key files missing" in {
+ val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+ val certFile = File.createTempFile("cert", ".pem")
+ val keyFile = File.createTempFile("key", ".pem")
+ try {
+ val writer = new BufferedWriter(new FileWriter(tmpwskprops))
+ writer.write(s"CERT=${certFile.getAbsolutePath()}\n")
+ writer.write(s"KEY=${keyFile.getAbsolutePath()}\n")
+ writer.close()
+ val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+ val stderr = wsk
+ .cli(
+ Seq("property", "get", "--apibuild", "--apihost", wskprops.apihost, "--apiversion", wskprops.apiversion),
+ env = env,
+ expectedExitCode = ERROR_EXIT)
+ .stderr
+ stderr should include regex ("""Unable to load the X509 key pair due to the following reason""")
+ } finally {
+ tmpwskprops.delete()
+ certFile.delete()
+ keyFile.delete()
+ }
+ }
+
it should "set api host with or without http prefix" in {
val tmpwskprops = File.createTempFile("wskprops", ".tmp")
try {
@@ -357,4 +423,70 @@ class WskConfigTests extends TestHelpers with WskTestHelpers {
}
tmpProps.delete()
}
+
+ it should "return configure the missing Cert file for action" in {
+ val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+ val keyFile = File.createTempFile("key", ".pem")
+ try {
+ val writer = new BufferedWriter(new FileWriter(tmpwskprops))
+ writer.write(s"KEY=${keyFile.getAbsolutePath()}\n")
+ writer.close()
+ val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+ val stderr = wsk
+ .cli(
+ Seq("action", "list", "--apihost", wskprops.apihost, "--apiversion", wskprops.apiversion),
+ env = env,
+ expectedExitCode = ERROR_EXIT)
+ .stderr
+ stderr should include regex ("""The Cert file is not configured. Please configure the missing Cert file.""")
+ } finally {
+ tmpwskprops.delete()
+ keyFile.delete()
+ }
+ }
+
+ it should "return configure the missing Key file for action" in {
+ val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+ val certFile = File.createTempFile("cert", ".pem")
+ try {
+ val writer = new BufferedWriter(new FileWriter(tmpwskprops))
+ writer.write(s"CERT=${certFile.getAbsolutePath()}\n")
+ writer.close()
+ val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+ val stderr = wsk
+ .cli(
+ Seq("action", "list", "--apihost", wskprops.apihost, "--apiversion", wskprops.apiversion),
+ env = env,
+ expectedExitCode = ERROR_EXIT)
+ .stderr
+ stderr should include regex ("""The Key file is not configured. Please configure the missing Key file.""")
+ } finally {
+ tmpwskprops.delete()
+ certFile.delete()
+ }
+ }
+
+ it should "return unable to load the X509 key pair with both Cert and Key files missing for action" in {
+ val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+ val certFile = File.createTempFile("cert", ".pem")
+ val keyFile = File.createTempFile("key", ".pem")
+ try {
+ val writer = new BufferedWriter(new FileWriter(tmpwskprops))
+ writer.write(s"CERT=${certFile.getAbsolutePath()}\n")
+ writer.write(s"KEY=${keyFile.getAbsolutePath()}\n")
+ writer.close()
+ val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+ val stderr = wsk
+ .cli(
+ Seq("action", "list", "--apihost", wskprops.apihost, "--apiversion", wskprops.apiversion),
+ env = env,
+ expectedExitCode = ERROR_EXIT)
+ .stderr
+ stderr should include regex ("""Unable to load the X509 key pair due to the following reason""")
+ } finally {
+ tmpwskprops.delete()
+ certFile.delete()
+ keyFile.delete()
+ }
+ }
}
diff --git a/tools/cli/go-whisk/whisk/client.go b/tools/cli/go-whisk/whisk/client.go
index 12bcbd4..7d502d8 100644
--- a/tools/cli/go-whisk/whisk/client.go
+++ b/tools/cli/go-whisk/whisk/client.go
@@ -94,28 +94,6 @@ var DefaultObfuscateArr = []ObfuscateSet{
func NewClient(httpClient *http.Client, config *Config) (*Client, error) {
- // Disable certificate checking in the dev environment if in insecure mode
- if config.Insecure {
- Debug(DbgInfo, "Disabling certificate checking.\n")
- var tlsConfig *tls.Config
- if config.Cert != "" && config.Key != "" {
- if cert, err := tls.LoadX509KeyPair(config.Cert, config.Key); err == nil {
- tlsConfig = &tls.Config{
- Certificates: []tls.Certificate{cert},
- InsecureSkipVerify: true,
- }
- }
- }else{
- tlsConfig = &tls.Config{
- InsecureSkipVerify: true,
- }
- }
-
- http.DefaultClient.Transport = &http.Transport{
- TLSClientConfig: tlsConfig,
- }
- }
-
if httpClient == nil {
httpClient = http.DefaultClient
}
@@ -162,11 +140,67 @@ func NewClient(httpClient *http.Client, config *Config) (*Client, error) {
return c, nil
}
+func (c *Client) LoadX509KeyPair() error {
+ tlsConfig := &tls.Config {
+ InsecureSkipVerify: c.Config.Insecure,
+ }
+
+ if c.Config.Cert != "" && c.Config.Key != "" {
+ Debug(DbgWarn, "both are fine.\n")
+ Debug(DbgWarn, c.Config.Cert)
+ Debug(DbgWarn, c.Config.Key)
+ if cert, err := ReadX509KeyPair(c.Config.Cert, c.Config.Key); err == nil {
+ Debug(DbgWarn, "both are fine good.\n")
+ tlsConfig.Certificates = []tls.Certificate{cert}
+ } else {
+ Debug(DbgWarn, "both are fine go to bad.\n")
+ errStr := wski18n.T("Unable to load the X509 key pair due to the following reason: {{.err}}",
+ map[string]interface{}{"err": err})
+ werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
+ return werr
+ }
+ } else if !c.Config.Insecure {
+ if c.Config.Cert == "" {
+ warningStr := "The Cert file is not configured. Please configure the missing Cert file, if there is a security issue accessing the service.\n"
+ Debug(DbgWarn, warningStr)
+ if c.Config.Key != "" {
+ errStr := wski18n.T("The Cert file is not configured. Please configure the missing Cert file.\n")
+ werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
+ return werr
+ }
+ }
+ if c.Config.Key == "" {
+ warningStr := "The Key file is not configured. Please configure the missing Key file, if there is a security issue accessing the service.\n"
+ Debug(DbgWarn, warningStr)
+ if c.Config.Cert != "" {
+ errStr := wski18n.T("The Key file is not configured. Please configure the missing Key file.\n")
+ werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
+ return werr
+ }
+ }
+ }
+
+ c.client.Transport = &http.Transport{
+ TLSClientConfig: tlsConfig,
+ }
+
+ return nil
+}
+
+var ReadX509KeyPair = func(certFile, keyFile string) (tls.Certificate, error) {
+ return tls.LoadX509KeyPair(certFile, keyFile)
+}
+
///////////////////////////////
// Request/Utility Functions //
///////////////////////////////
func (c *Client) NewRequest(method, urlStr string, body interface{}, includeNamespaceInUrl bool) (*http.Request, error) {
+ werr := c.LoadX509KeyPair()
+ if werr != nil {
+ return nil, werr
+ }
+
if (includeNamespaceInUrl) {
if c.Config.Namespace != "" {
urlStr = fmt.Sprintf("%s/namespaces/%s/%s", c.Config.Version, c.Config.Namespace, urlStr)
@@ -608,6 +642,10 @@ func (c *Client) NewRequestUrl(
useAuthentication bool) (*http.Request, error) {
var requestUrl *url.URL
var err error
+ error := c.LoadX509KeyPair()
+ if error != nil {
+ return nil, error
+ }
if (appendOpenWhiskPath) {
var urlVerNamespaceStr string
diff --git a/tools/cli/go-whisk/whisk/info.go b/tools/cli/go-whisk/whisk/info.go
index b97344c..777b822 100644
--- a/tools/cli/go-whisk/whisk/info.go
+++ b/tools/cli/go-whisk/whisk/info.go
@@ -38,6 +38,10 @@ type InfoService struct {
func (s *InfoService) Get() (*Info, *http.Response, error) {
// make a request to c.BaseURL / v1
+ err := s.client.LoadX509KeyPair()
+ if err != nil {
+ return nil, nil, err
+ }
urlStr := fmt.Sprintf("%s/%s", s.client.BaseURL.String(), s.client.Config.Version)
u, err := url.Parse(urlStr)
if err != nil {
diff --git a/tools/cli/go-whisk/whisk/sdk.go b/tools/cli/go-whisk/whisk/sdk.go
index df3178a..7a67dc9 100644
--- a/tools/cli/go-whisk/whisk/sdk.go
+++ b/tools/cli/go-whisk/whisk/sdk.go
@@ -39,7 +39,10 @@ type SdkRequest struct {
// Install artifact {component = docker || swift || iOS}
func (s *SdkService) Install(relFileUrl string) (*http.Response, error) {
-
+ err := s.client.LoadX509KeyPair()
+ if err != nil {
+ return nil, err
+ }
baseURL := s.client.Config.BaseURL
// Remove everything but the scheme, host, and port
baseURL.Path, baseURL.RawQuery, baseURL.Fragment = "", "", ""
diff --git a/tools/cli/go-whisk/wski18n/resources/en_US.all.json b/tools/cli/go-whisk/wski18n/resources/en_US.all.json
index e473202..45d5393 100644
--- a/tools/cli/go-whisk/wski18n/resources/en_US.all.json
+++ b/tools/cli/go-whisk/wski18n/resources/en_US.all.json
@@ -122,5 +122,17 @@
{
"id": "The connection failed, or timed out. (HTTP status code {{.code}})",
"translation": "The connection failed, or timed out. (HTTP status code {{.code}})"
+ },
+ {
+ "id": "Unable to load the X509 key pair due to the following reason: {{.err}}",
+ "translation": "Unable to load the X509 key pair due to the following reason: {{.err}}"
+ },
+ {
+ "id": "The Cert file is not configured. Please configure the missing Cert file.\n",
+ "translation": "The Cert file is not configured. Please configure the missing Cert file.\n"
+ },
+ {
+ "id": "The Key file is not configured. Please configure the missing Key file.\n",
+ "translation": "The Key file is not configured. Please configure the missing Key file.\n"
}
]
--
To stop receiving notification emails like this one, please contact
['"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>'].