Skip to content
Permalink
Browse files

Adding support to encrypt values for the config file.

  • Loading branch information...
atooni committed Mar 16, 2019
1 parent 5180ddf commit 09c1727433c6186d495f93042181058154597cb5
@@ -2,6 +2,7 @@ package blended.container.context.api

import java.util.concurrent.atomic.AtomicLong

import blended.security.crypto.ContainerCryptoSupport
import com.typesafe.config.Config

object ContainerContext {
@@ -3,7 +3,8 @@ package blended.container.context.impl.internal
import java.io.File
import java.util.Properties

import blended.container.context.api.{ContainerContext, ContainerCryptoSupport}
import blended.container.context.api.ContainerContext
import blended.security.crypto.{ContainerCryptoSupport, BlendedCryptoSupport}
import blended.updater.config.{LocalOverlays, OverlayRef, RuntimeConfig}
import blended.util.logging.Logger
import com.typesafe.config.{Config, ConfigFactory, ConfigParseOptions}
@@ -97,7 +98,7 @@ class ContainerContextImpl() extends ContainerContext {
"secret"
}

ContainerCryptoSupportImpl.initCryptoSupport(
BlendedCryptoSupport.initCryptoSupport(
new File(getContainerConfigDirectory(), cipherSecretFile).getAbsolutePath()
)
}
@@ -1,6 +1,7 @@
package blended.container.context.impl.internal

import blended.container.context.api.{ContainerContext, ContainerCryptoSupport, ContainerIdentifierService, PropertyResolverException}
import blended.container.context.api.{ContainerContext, ContainerIdentifierService, PropertyResolverException}
import blended.security.crypto.{BlendedCryptoSupport, ContainerCryptoSupport}
import com.typesafe.config.Config
import org.scalatest.{FreeSpec, Matchers}

@@ -28,7 +29,7 @@ class PropertyResolverSpec extends FreeSpec

override def getContainerConfig() : Config = ???

override def getContainerCryptoSupport(): ContainerCryptoSupport = new ContainerCryptoSupportImpl("secret", "AES")
override def getContainerCryptoSupport(): ContainerCryptoSupport = BlendedCryptoSupport.initCryptoSupport("secret")
}

val idSvc : ContainerIdentifierService = new ContainerIdentifierService {
@@ -116,10 +117,10 @@ class PropertyResolverSpec extends FreeSpec
// ContainerPropertyResolver.resolve(idSvc, "${{#replace('$[[typeA]]')}}") should be ("1")
ContainerPropertyResolver.resolve(idSvc, "$[[typeB(replace:A:1,replace:B:2))]]") should be ("2")

val enc : String = idSvc.getContainerContext().getContainerCryptoSupport().encrypt("$[[foo]]").get
val enc : String = idSvc.getContainerContext().getContainerCryptoSupport().encrypt("$[[foo]]$[[foo(upper)]]").get
val line = "$[encrypted[" + enc + "]]"

ContainerPropertyResolver.resolve(idSvc, line) should be ("bar")
ContainerPropertyResolver.resolve(idSvc, line) should be ("barBAR")
}

"should allow to delay the property resolution" in {
@@ -0,0 +1,35 @@
#!/bin/sh

function setenv() {

if [ -f "$BLENDED_HOME/bin/setenv" ] ; then
. "$BLENDED_HOME/bin/setenv"
fi
}

function blended_home() {

home=$1

if [ "x$BLENDED_HOME" == "x" ] ; then
OLDDIR=$(pwd)
dir="$(dirname $0)/.."
cd $dir
home=$(pwd)
cd $OLDDIR
fi

echo "$home"
}

export BLENDED_HOME=$(blended_home $BLENDED_HOME)
cd $BLENDED_HOME

# column-separated
ENC_CP="${BLENDED_HOME}/lib/*"

exec ${JAVA_HOME}/bin/java\
-cp\
"${ENC_CP}"\
blended.security.crypto.Encryptor\
"$@"
@@ -1,37 +1,40 @@
package blended.container.context.impl.internal
package blended.security.crypto

import java.io.File
import java.security.Key

import blended.container.context.api.ContainerCryptoSupport
import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec

import scala.io.Source
import scala.util.Try

object ContainerCryptoSupportImpl {
object BlendedCryptoSupport {

def initCryptoSupport(fileName : String) : ContainerCryptoSupport = {

val secretFromFile : Array[Char] =
(Source.fromFile(
new File(fileName)
).getLines().toList.headOption.getOrElse("vczP26-QZ5n%$8YP") + ("*" * 16))
.substring(0,16)
.toCharArray()
val defaultPwd : String = "vczP26-QZ5n%$8YP"
val f : File = new File(fileName)

val pwd : String = if (f.exists() && f.isFile() && f.canRead()) {
Source.fromFile(f).getLines().toList.headOption.getOrElse(defaultPwd)
} else {
defaultPwd
}

val secretFromFile : Array[Char] = (pwd + "*" + 16).substring(0,16).toCharArray()

val secret : String = {
val salt : Array[Char] = ("V*YE6FPXW6#!g^hD" + "*" * 16).substring(0,16).toCharArray()
val mixed : String = secretFromFile.zip(salt).map { case (a,b) => a.toString + b.toString} mkString("")
mixed.substring(0,16)
}

new ContainerCryptoSupportImpl(secret, "AES")
new BlendedCryptoSupport(secret, "AES")
}
}

class ContainerCryptoSupportImpl(secret : String, alg : String) extends ContainerCryptoSupport {
class BlendedCryptoSupport(secret : String, alg : String) extends ContainerCryptoSupport {

private val KEYBYTES = 16

@@ -0,0 +1,58 @@
package blended.security.crypto

import de.tototec.cmdoption.{CmdOption, CmdlineParser}

import scala.util.{Failure, Success}

object BlendedEncryptor {

def main(args: Array[String]): Unit = run(args)

def run(args : Array[String]) : Unit = {

val cmdLine = new CmdLine()
val cp = new CmdlineParser(cmdLine)
cp.setAboutLine("Standalone client to encrypt plain Strings to be included in the config files.")
cp.parse(args:_*)

if (cmdLine.help || args.isEmpty) {
cp.usage()
throw new NoArgsProvidedException
}

val cs : ContainerCryptoSupport = BlendedCryptoSupport.initCryptoSupport(cmdLine.secret)

cmdLine.plain.foreach { p =>
cs.encrypt(p) match {
case Failure(t) =>
System.err.println(s"Could not encrypt [$p] : [${t.getMessage()}]")
case Success(e) =>
System.out.println(s"Encrypted value for [$p] : [$e]")
}
}
}

private class NoArgsProvidedException extends Exception("No command line arguments provided.")

private class CmdLine {

@CmdOption(names = Array("--help", "-h"), description = "Show this help", isHelp = true)
var help: Boolean = false

@CmdOption(
names = Array("--secret", "-s"),
args = Array("file"),
description = "The name of the file containing the secret for encrypting the plain string."
)
var _secret : String = _
def secret : String = Option(_secret).getOrElse("secret")

@CmdOption(
names = Array("--plain", "-p"),
args = Array("text"),
description = "The plain text to encrypt."
)
var _plain : String = _
def plain = Option(_plain)
}
}
@@ -1,4 +1,4 @@
package blended.container.context.api
package blended.security.crypto

import scala.util.Try

@@ -1,18 +1,18 @@
package blended.container.context.impl.internal
package blended.security.crypto

import blended.testsupport.scalatest.LoggingFreeSpec
import blended.util.logging.Logger
import org.scalatest.Matchers
import org.scalatest.prop.PropertyChecks

class ContainerCryptoSupportSpec extends LoggingFreeSpec
class BlendedCryptoSupportSpec extends LoggingFreeSpec
with Matchers
with PropertyChecks {

private val log : Logger = Logger[ContainerCryptoSupportImpl]
private val log : Logger = Logger[BlendedCryptoSupport]

private val secret : String = "secret"
private val cs : ContainerCryptoSupportImpl = new ContainerCryptoSupportImpl(secret, "AES")
private val cs : BlendedCryptoSupport = new BlendedCryptoSupport(secret, "AES")

"The Crypto Support should" - {

@@ -2,9 +2,8 @@ package blended.security.scep.standalone

import java.io.File

import blended.container.context.api.{ContainerContext, ContainerCryptoSupport}
import blended.container.context.impl.internal.ContainerContextImpl.SECRET_FILE_PATH
import blended.container.context.impl.internal.ContainerCryptoSupportImpl
import blended.container.context.api.ContainerContext
import blended.security.crypto.{BlendedCryptoSupport, ContainerCryptoSupport}
import com.typesafe.config.{Config, ConfigFactory, ConfigParseOptions}

class ScepAppContainerContext(baseDir: String) extends ContainerContext {
@@ -32,7 +31,7 @@ class ScepAppContainerContext(baseDir: String) extends ContainerContext {
"secret"
}

ContainerCryptoSupportImpl.initCryptoSupport(
BlendedCryptoSupport.initCryptoSupport(
new File(getContainerConfigDirectory(), cipherSecretFile).getAbsolutePath()
)
}
@@ -3,8 +3,8 @@ package blended.testsupport.pojosr
import java.io.File
import java.util.Properties

import blended.container.context.api.{ContainerContext, ContainerCryptoSupport}
import blended.container.context.impl.internal.ContainerCryptoSupportImpl
import blended.container.context.api.ContainerContext
import blended.security.crypto.{BlendedCryptoSupport, ContainerCryptoSupport}
import com.typesafe.config.impl.Parseable
import com.typesafe.config.{Config, ConfigFactory, ConfigObject, ConfigParseOptions}

@@ -33,7 +33,7 @@ class MockContainerContext(baseDir: String) extends ContainerContext {
"secret"
}

ContainerCryptoSupportImpl.initCryptoSupport(
BlendedCryptoSupport.initCryptoSupport(
new File(getContainerConfigDirectory(), cipherSecretFile).getAbsolutePath()
)
}
@@ -91,6 +91,7 @@ lazy val blendedJolokia = BlendedJolokia.project
lazy val blendedSamplesCamel = BlendedSamplesCamel.project
lazy val blendedSamplesJms = BlendedSamplesJms.project
lazy val blendedAkkaHttpSampleHelloworld = BlendedAkkaHttpSampleHelloworld.project
lazy val blendedSecurityCrypto = BlendedSecurityCrypto.project
// Referenced in adoc file: doc/content/BUILDING.adoc
// tag::Building[]
lazy val blendedActivemqClient = BlendedActivemqClient.project
@@ -151,6 +152,7 @@ lazy val jvmProjects : Seq[ProjectReference] = Seq(
blendedSecurityTest,
blendedSecuritySsl,
blendedSecurityScep,
blendedSecurityCrypto,
blendedSecurityScepStandalone,
blendedHawtioLogin,
blendedJolokia,
@@ -1,3 +1,4 @@
import sbt._
import blended.sbt.Dependencies

object BlendedContainerContextApi extends ProjectFactory {
@@ -15,6 +16,8 @@ object BlendedContainerContextApi extends ProjectFactory {
)
)

override val project = helper.baseProject
override val project = helper.baseProject.dependsOn(
BlendedSecurityCrypto.project
)

}
@@ -29,6 +29,7 @@ object BlendedContainerContextImpl extends ProjectFactory {
)

override val project = helper.baseProject.dependsOn(
BlendedSecurityCrypto.project,
BlendedContainerContextApi.project,
BlendedUtilLogging.project,
BlendedUtil.project,
@@ -115,6 +115,7 @@ object BlendedLauncher extends ProjectFactory {
override val project = helper.baseProject.dependsOn(
BlendedUtilLogging.project,
BlendedUpdaterConfigJvm.project,
BlendedSecurityCrypto.project,

BlendedTestsupport.project % "test"
)
@@ -0,0 +1,35 @@
import blended.sbt.Dependencies
import de.wayofquality.sbt.testlogconfig.TestLogConfig.autoImport._
import sbt._

object BlendedSecurityCrypto extends ProjectFactory {

private[this] val helper = new ProjectSettings(
projectName = "blended.security.crypto",
description = "Provides classes and mainline for encrypting / decrypting arbitrary Strings.",
deps = Seq(
Dependencies.cmdOption,

Dependencies.scalatest % "test",
Dependencies.scalacheck % "test",
Dependencies.logbackCore % "test",
Dependencies.logbackClassic % "test"
),
adaptBundle = b => b.copy(
importPackage = Seq(
"de.tototec.cmdoption;resolution:=optional"
),
exportPackage = Seq(
b.bundleSymbolicName
)
)
) {
override def settings: Seq[sbt.Setting[_]] = defaultSettings ++ Seq(
Test / testlogDefaultLevel := "INFO"
)
}

override val project = helper.baseProject.dependsOn(
BlendedTestsupport.project % "test"
)
}

0 comments on commit 09c1727

Please sign in to comment.
You can’t perform that action at this time.