Skip to content

Commit

Permalink
Mutual TLS support added for Activity (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
nareshkumarthota authored and rameshpolishetti committed Sep 22, 2017
1 parent e3524e4 commit f93a27f
Show file tree
Hide file tree
Showing 5 changed files with 264 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"mashling_schema": "0.2",
"gateway": {
"name": "clientAuthGw",
"name": "secureGwApp",
"version": "1.0.0",
"display_name":"Secure Rest Conditional Gateway",
"display_image":"displayImage.svg",
Expand All @@ -22,8 +22,8 @@
"settings": {
"port": "9097",
"enableTLS": "true",
"serverCert":"${ENV.SERVER_CERT}",
"serverKey":"${ENV.SERVER_KEY}"
"serverCert":"gateway.crt",
"serverKey":"gateway.key"
}
},
{
Expand All @@ -33,10 +33,10 @@
"settings": {
"port": "9098",
"enableTLS": "true",
"serverCert":"/Users/rpolishe/sslcerts/domain.crt",
"serverKey":"/Users/rpolishe/sslcerts/domain.key",
"serverCert":"gateway.crt",
"serverKey":"gateway.key",
"enableClientAuth": "true",
"trustStore": "${ENV.TRUST_STORE}"
"trustStore": "truststore"
}
}
],
Expand Down Expand Up @@ -106,6 +106,11 @@
"name": "animals_get_handler",
"description": "Handle other animals",
"reference": "github.com/TIBCOSoftware/mashling/lib/flow/RestTriggerToRestGetActivity.json"
},
{
"name": "animals_get_handler_mutual_ssl",
"description": "Handle other animals",
"reference": "github.com/TIBCOSoftware/mashling/lib/flow/SecureRestInvoker.json"
}
],
"event_links": [
Expand Down Expand Up @@ -145,7 +150,7 @@
"triggers": ["get_animals_rest_secure_client_auth_trigger"],
"dispatches": [
{
"handler": "animals_get_handler"
"handler": "animals_get_handler_mutual_ssl"
}
]
}
Expand Down
16 changes: 16 additions & 0 deletions ext/flogo/activity/rest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ Inputs and Outputs:
{
"name": "tracing",
"type": "any"
},
{
"name": "serverCert",
"type": "string"
},
{
"name": "serverKey",
"type": "string"
},
{
"name": "trustStore",
"type": "string"
}
],
"outputs": [
Expand All @@ -63,6 +75,10 @@ Inputs and Outputs:
| content | The message content |
| params | The path parameters (Deprecated) |
| tracing | The tracing context to forward |
| serverCert | The server certificate file path |
| serverKey | The server key file path |
| trustStore | Folder path containing trusted certificates |

Note:

* **pathParams**: Is only required if you have params in your URI ( i.e. http://.../pet/:id )
Expand Down
81 changes: 80 additions & 1 deletion ext/flogo/activity/rest/activity.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ package rest

import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"os"
"strings"

"github.com/TIBCOSoftware/flogo-lib/core/activity"
Expand All @@ -32,6 +36,9 @@ const (
ivContent = "content"
ivParams = "params"
ivTracing = "tracing"
ivServerCert = "serverCert"
ivServerKey = "serverKey"
ivTrustStore = "trustStore"

ovResult = "result"
ovTracing = "tracing"
Expand Down Expand Up @@ -144,7 +151,47 @@ func (a *RESTActivity) Eval(context activity.Context) (done bool, err error) {
opentracing.HTTPHeadersCarrier(req.Header))
}

client := &http.Client{}
//Enable transport layaer security
log.SetLogLevel(logger.DebugLevel)

serverCert, _ := context.GetInput(ivServerCert).(string)
serverKey, _ := context.GetInput(ivServerKey).(string)
trustStore, _ := context.GetInput(ivTrustStore).(string)

tlsConfig := &tls.Config{}

if serverCert != "" && serverKey != "" {
//gateway certificates are available
//load gateway certificate-key pair
log.Debug("Loading gateway certificate - key pair...")
cert, err := tls.LoadX509KeyPair(serverCert, serverKey)
if err != nil {
log.Errorf("Unable to load cert - %v", err)
} else {
tlsConfig.Certificates = []tls.Certificate{cert}
log.Debug("Loading gateway certificate - key pair DONE")
}
}

if trustStore != "" {
//trust store directory is available
//load trusted certificates present inside the dir
log.Debug("Loading truststore...")
trustRootCAPool, err := getCerts(trustStore)
if err != nil {
log.Errorf("Error while loading trust store - %v", err)
} else {
tlsConfig.RootCAs = trustRootCAPool
log.Debug("Loading truststore DONE")
}
}

tlsConfig.BuildNameToCertificate()

client := &http.Client{
Transport: &http.Transport{TLSClientConfig: tlsConfig},
}

resp, err := client.Do(req)
if err != nil {
if span != nil {
Expand Down Expand Up @@ -263,3 +310,35 @@ func BuildURI(uri string, values map[string]string) string {

return buffer.String()
}

func getCerts(trustStore string) (*x509.CertPool, error) {
certPool := x509.NewCertPool()
fileInfo, err := os.Stat(trustStore)
if err != nil {
return certPool, fmt.Errorf("Truststore [%s] does not exist", trustStore)
}
switch mode := fileInfo.Mode(); {
case mode.IsDir():
break
case mode.IsRegular():
return certPool, fmt.Errorf("Truststore [%s] is not a directory. Must be a directory containing trusted certificates in PEM format",
trustStore)
}
trustedCertFiles, err := ioutil.ReadDir(trustStore)
if err != nil || len(trustedCertFiles) == 0 {
return certPool, fmt.Errorf("Failed to read trusted certificates from [%s] Must be a directory containing trusted certificates in PEM format", trustStore)
}
for _, trustCertFile := range trustedCertFiles {
fqfName := fmt.Sprintf("%s%c%s", trustStore, os.PathSeparator, trustCertFile.Name())
trustCertBytes, err := ioutil.ReadFile(fqfName)
if err != nil {
log.Warnf("Failed to read trusted certificate [%s] ... continueing", trustCertFile.Name())
}
log.Debugf("Loading cert file - %v", fqfName)
certPool.AppendCertsFromPEM(trustCertBytes)
}
if len(certPool.Subjects()) < 1 {
return certPool, fmt.Errorf("Failed to read trusted certificates from [%s] After processing all files in the directory no valid trusted certs were found", trustStore)
}
return certPool, nil
}
12 changes: 12 additions & 0 deletions ext/flogo/activity/rest/activity.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@
{
"name": "tracing",
"type": "any"
},
{
"name": "serverCert",
"type": "string"
},
{
"name": "serverKey",
"type": "string"
},
{
"name": "trustStore",
"type": "string"
}
],
"outputs": [
Expand Down
144 changes: 144 additions & 0 deletions lib/flow/SecureRestInvoker.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
{
"name": "newapp",
"type": "flogo:app",
"version": "0.0.1",
"description": "",
"triggers": [
{
"name": "gorillamuxtrigger",
"ref": "github.com/TIBCOSoftware/mashling/ext/flogo/trigger/gorillamuxtrigger",
"description": "gorillamuxtrigger REST Trigger",
"settings": {
"port": "9096"
},
"id": "receive_http_message",
"handlers": [
{
"settings": {
"method": "GET",
"path": "/users/:id",
"autoIdReply": "false",
"useReplyHandler": "false"
},
"actionId": "check"
}
]
}
],
"actions": [
{
"name": "check",
"data": {
"flow": {
"type": 1,
"explicitReply": true,
"attributes": [],
"rootTask": {
"id": 1,
"type": 1,
"tasks": [
{
"id": 2,
"name": "Invoke REST Service",
"description": "Simple REST Activity",
"type": 1,
"activityType": "github-com-tibco-software-flogo-contrib-activity-rest",
"activityRef": "github.com/TIBCOSoftware/mashling/ext/flogo/activity/rest",
"attributes": [
{
"name": "method",
"value": "GET",
"required": true,
"type": "string"
},
{
"name": "uri",
"value": "https://localhost:8080/",
"required": true,
"type": "string"
},
{
"name": "pathParams",
"value": null,
"required": false,
"type": "params"
},
{
"name": "queryParams",
"value": null,
"required": false,
"type": "params"
},
{
"name": "content",
"value": null,
"required": false,
"type": "any"
},
{
"name": "serverCert",
"value": "gateway.crt",
"required": false,
"type": "string"
},
{
"name": "serverKey",
"value": "gateway.key",
"required": false,
"type": "string"
},
{
"name": "trustStore",
"value": "truststore",
"required": false,
"type": "string"
}
]
},
{
"id": 3,
"name": "Reply To Trigger",
"description": "Simple Reply Activity",
"type": 1,
"activityType": "github-com-tibco-software-flogo-contrib-activity-reply",
"activityRef": "github.com/TIBCOSoftware/flogo-contrib/activity/reply",
"attributes": [
{
"name": "code",
"value": "200",
"required": true,
"type": "integer"
},
{
"name": "data",
"value": "success",
"required": false,
"type": "any"
}
],
"inputMappings": [
{
"type": 1,
"value": "{A2.result}",
"mapTo": "data"
}
]
}
],
"links": [
{
"id": 1,
"from": 2,
"to": 3,
"type": 0
}
],
"attributes": []
}
}
},
"id": "check",
"ref": "github.com/TIBCOSoftware/flogo-contrib/action/flow"
}
]
}

0 comments on commit f93a27f

Please sign in to comment.