AnsweredAssumed Answered

Is it possible to use a certificate component inside of a http call in a custom groovy script?

Question asked by forivall on Mar 2, 2017
Latest reply on Mar 3, 2017 by forivall

I created a groovy script for proxying generic http calls from a listener to an intranet server (especially since multipart/form-data isn't supported by the HTTP connector yet). However, since the server I'm connecting to is using a self-signed certificate, i'm currently including that inline. I'm wondering if there's any way to retrieve certificates from our components, or should I convert this into a full custom connector?

 

import com.boomi.document.scripting.DataContextImpl
import com.boomi.execution.ExecutionManager
import com.boomi.execution.ExecutionTask

import javax.net.ssl.HttpsURLConnection
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory
import java.security.KeyStore
import java.security.cert.CertificateFactory
import java.util.Map.Entry

String HOSTNAME = "internal.dns.hostname"
String CERTIFICATE = "-----BEGIN CERTIFICATE-----\n" +
  "(PEM / Base-64 Formatted Certificate data here)\n" +
  "-----END CERTIFICATE-----"

ExecutionTask task = ExecutionManager.current

Properties execProps = task.properties
DataContextImpl context = dataContext

def INHEADER_PREFIX = 'document.dynamic.userdefined.inheader_'
int INHEADER_PREFIX_LEN = INHEADER_PREFIX.length()


def QUERY_PREFIX = 'query_'
int QUERY_PREFIX_LEN = QUERY_PREFIX.length()


// TODO: figure out how to load certificate from here instead of inline as above
// CertificateFactory cf = CertificateFactory.getInstance(task.accountConfig)

// reassemble the URL
pathParts = []


1.upto(9) { n ->
  pathPart = execProps.getProperty("param_path$n")
  if (pathPart != null && pathPart.size() > 0) {
    pathParts << pathPart
  }
}

String path = pathParts.join('/')

queryParams = []

for (entry in execProps.entrySet()) {
  String k = entry.key
  String v = entry.value as String
  if (k.startsWith(QUERY_PREFIX)) {
     queryParams << k.substring(QUERY_PREFIX_LEN) + '=' + URLEncoder.encode(v, 'UTF-8')
  }
}

if (queryParams.size() > 0) {
  path += '?' + queryParams.join('&')
}

String fullPath = (execProps.getProperty('http_proxy_url_base') as String) + '/' + path
URL url = new URL(fullPath)
String httpMethod = execProps.getProperty('inmethod')

context.getDataCount().times { i ->
  InputStream is = dataContext.getStream(i)
  Properties docProps = dataContext.getProperties(i)

  HttpURLConnection conn = url.openConnection() as HttpURLConnection

  if (url.protocol == 'https') {
    HttpsURLConnection sconn = conn as HttpsURLConnection

    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType())
    ks.load(null, null)

    CertificateFactory cf = CertificateFactory.getInstance('X.509')
    ks.setCertificateEntry(HOSTNAME, cf.generateCertificate(new ByteArrayInputStream(CERTIFICATE.bytes)))

    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
    tmf.init(ks)

    SSLContext sc = SSLContext.getInstance("SSLv3")
    sc.init(null, tmf.getTrustManagers(), null)

    // sc.init(null, [new LooseTrustManager()], new SecureRandom())
    // SSLContext sc = SSLContext.getDefault()
    sconn.SSLSocketFactory = sc.socketFactory

  }

  conn.requestMethod = httpMethod


  for (entry in docProps.entrySet()) {
    String k = entry.key
    if (k.startsWith(INHEADER_PREFIX)) {
      conn.setRequestProperty(k.substring(INHEADER_PREFIX_LEN), entry.value as String)
    }
  }

  if (conn.requestMethod != 'GET' && conn.requestMethod != 'HEAD') {
    conn.doOutput = true
    OutputStream os = conn.getOutputStream()

    // pipe the inputStream to the outputStream
    byte[] buffer = new byte[1024]

    int len
    while ((len = is.read(buffer)) != -1) {
      os.write(buffer, 0, len)
    }
  }

  // done request
  docProps.setProperty('document.dynamic.userdefined.outstatuscode', "${conn.responseCode}")



  Map<String, List<String>> headerFields = conn.headerFields
  for (entry in headerFields.entrySet()) {
    String k = entry.key
    List<String> v = entry.value
    if (k != null && v.size() > 0) {
      docProps.setProperty("document.dynamic.userdefined.outheader_$k", v.get(0))
    }
  }

  InputStream connIs
  try {
    connIs = conn.getInputStream()
  } catch (IOException err) {
    connIs = conn.getErrorStream()
  }
  dataContext.storeStream(connIs, docProps)
}

Outcomes