Secure txscalacsharp

Post on 18-Dec-2014

179 views 0 download

description

 

Transcript of Secure txscalacsharp

Álvaro Rodríguez

@alvrod

PayTrue

Características generales de C#

Ejemplos comparados

Observaciones

var zero = 0;var numbers = new[] {1, 2, 3, 4};numbers.Select(x => x / zero).ToList();

Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero.at Test.Application.<>c__DisplayClass3.<Main>b__2(Int32 x) in F:\Visual Studio

Projects\ScalaVsCs\Program.cs:line 21at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)at Test.Application.Main() in F:\Visual Studio Projects\ScalaVsCs\Program.cs:line 21

wat

Scala

C#

def upperCase(args: Array[String]) { val res = for (a <- args) yield a.toUpperCaseprintln("Arguments: " + res.mkString)

}…upperCase(Array ("a", "b", "c"))

public static void UpperCase(string[] args) {var res = from arg in args select arg.ToUpperInvariant();Console.Out.WriteLine("Arguments: {0}", String.Join("", res));

}…UpperCase(new []{"a", "b", "c"});

Scala

C#

def upperCase(args: Array[String]) { val res = for (a <- args) yield a.toUpperCaseprintln("Arguments: " + res.mkString)

}…upperCase(Array ("a", "b", "c"))

public static IEnumerable<string> UpperCaseYield(string[] args) {foreach (var arg in args) {yield return arg.ToUpperInvariant();

}}

object implicits {implicit def arrayWrapper[A : ClassTag](x: Array[A]) = new { def sort(p: (A, A) => Boolean) = {

util.Sorting.stableSort(x, p); x }

} }

import implicits._ …

Scala

val numbers = Array(2, 3, 1, 4) numbers.sort((x: Int, y: Int) => x < y))

C#public static class implicits {

public static IList<T> MySort<T>(this IList<T> list, Func<T, T, int> func) where T : class {

var temp = list.ToArray();Array.Sort(temp, (x, y) => func(x, y));return temp;

}}

var objects = new[] {"a", "b", "c"}; objects.MySort(String.CompareOrdinal);

Pattern matching

Inmutabilidad

Inferencia de tipos

Locuacidad (DSL)

Expressions everywhere

Option > null, Nullable<T>

trait >>>> interface

case class > auto-properties

macros / compiler-as-a-service > roslyn

Automatic Resource Management Scala, a través de librerías

C#, magia en el compilador

Debatible Madurez

dynamic

async / await

Código nativo

Xamarin

JVM

Scala

CLR

C# tiene bastantes cosas, aunque a veces la sintaxis no es la mejor

F#

“Scala feels closer to Java than F# to C#”

Java-----C#-------Scala-------------------F#

let zero = 0let numbers = [| 1; 2; 3 |]Seq.map(fun x -> x / zero) numbers |> Seq.length

System.DivideByZeroException: Attempted to divide by zero.

at FSI_0002.it@7-1.Invoke(Int32 x) <- watat Microsoft.FSharp.Collections.IEnumerator.map@116.DoMoveNext(b& )at Microsoft.FSharp.Collections.IEnumerator.MapEnumerator`1.System-Collections-IEnumerator-

MoveNext()at Microsoft.FSharp.Collections.SeqModule.Length[T](IEnumerable`1 source)at <StartupCode$FSI_0002>.$FSI_0002.main@()at main@dm()

Stopped due to error

Una breve introducción a la industria de tarjetas de crédito

Por qué el proyecto vale la pena

Visión funcional de la aplicación

MasterCard, VISA, American Express

Esquema descentralizado de cobertura mundial

Iniciativas para nuevos negocios, control de fraude Chip & PIN (EMV), “Verified By Visa”,

etc.

PCI Council PCI DSS

Data Security Standard

Aplicable a ambientes productivos

PA DSS

Aplicable a aplicaciones de pagos

Estándares de seguridad para proteger información sensible de tarjetas y prevenir fraude

Obligatorios para proveedores de servicio, comercios, etc.

Apuntan a impedir el acceso pero también a desvalorizar la información

Nº de tarjeta, tracks, PIN, en claro, “por todos lados”CRM, contabilidad, facturación, etc. etc.

Sistemas no preparados para cumplir con la norma PCI DSS

Enorme costo de adaptación

La norma en sí es cara y difícil de cumplir

El estándar tiene más de 260 requisitos individuales, afectando desde políticas de RRHH hasta el control de qué servicios se ejecutan en cada computadora dentro del “ambiente de tarjetas PCI”

Análisis GAP: 2 meses

Proyecto PCI: 7 meses

Certificación / ajustes: 2 meses

~2 millones U$S

+

200.000 – 500.000+ U$S / añoen auditorías

Cada módulo de software que deba certificarse tiene un sobrecosto enorme por los requisitos técnicos.

Documentación

Detalles de logging, seguridad, estándares

Evidencia de procesos de desarrollo seguro, etc.

Criptografía -> gestión de claves

PCI aplica sólo a “sistemas que almacenan, procesan o transmiten el nº de tarjeta”

La forma más fácil de “certificar PCI” entonces es evitar almacenar, procesar o transmitir el nº de tarjeta

SecureTX es PA-DSS, el resto queda fuera de la norma

Estrategia de reducción del alcance a través de tokenización

def tokenize(card:String): String

5588 3201 2345 6789

->

1000 0000 4365 6789

Desarrollo de middleware tokenizador “Secure TX”

Diseño con Akka

Implementación

Observaciones. Discusión.

“Tokenizer” es un servicio web aparte

“SecureTX switch”es la aplicación que estamos discutiendo

“Authorizer / switch”podría ser un procesador de pagos cualquiera

El esquema de la derecha es minimal, se dan escenarios más complejos

Transaction

storage

Authorizer /

switch

SecureTX

switch

SecureTX

tokenizer

Encrypted card

storage

TX

1

2

34

5

Producto caja, cerrado

Distintos canales

TCP

JMS

Distintos formatos

ISO 8583 en distintos sabores

ASCII largo fijo

Distintos flujos

Camino crítico transaccional

Estabilidad

Performance

Akka

Librería y runtime para desarrollar aplicaciones para la JVM

Altamente concurrentes

Distribuidas

Con tolerancia a fallas

Orientadas a eventos asincrónicos

Modelo de actores

Cada actor tiene un mailbox de eventos: mensajes que procesa secuencialmente

Modelo de ejecución simplificado, fácil de entender y evitar problemas típicos de concurrencia

Modelo de supervisión para tolerancia a fallas

Meta-actores (p.e. para distribución de carga)

Librería para integración de mensajes

“Todos con todos” de canales x formatos

Canales: JMS, Archivos, HTTP, … …

Formatos: Largo fijo, CSV, XML, JSON, etc.

Muy configurable mediante Spring

Rutas, endpoints, etc.

EAI patterns en código o XML

Akka – Camel integra ambas librerías

SecureTX "Switch"

Switch

Tokenizer

PaymentProcessorSender

PaymentProcessorReceiver

ManagementReceiver

ManagementSender

TcpServerA

TcpServerB

TcpClientD

HSM

Tokenizer Service

Authorizer

HSM Server

POS Network

E Gateway

VISA

MasterCard

TcpClientE

TCP, HSM – Akka.IO 2.2 en Scala

Precisamos full-duplex asincrónico, y Camel es one-way o request-reply

Binario + ISO8583 o “ASCII largo fijo” configurable

Tokenizer, PaymentProcessor, Management

Camel

En principio:

Tokenizer por HTTP4

PaymentProcessor, Management por JMS

Pero parte de la gracia de Camel es que esto es muy configurable

class Tokenizer extends Actor with Producer with akka.actor.ActorLogging {

val config = SwApp.appConfigContext.getBean(self.path.name).asInstanceOf[TokenizerBean]

val contextHeader = "TOKENIZER_CONTEXT"

val cardIdResource = "cardid"

val cardNumberResource = "cardnumber"

def endpointUri: String = s"http4://${config.host}:${config.port}"

override def transformOutgoingMessage(msg: Any) = msg match {

case TokenizeRequest(cardNumber, senderContext) => CreateCamelMessage(cardIdResource, cardNumber, senderContext)

case OpenCardRequest(token, senderContext) => CreateCamelMessage(cardNumberResource, token, senderContext)

}

private def CreateCamelMessage(resource:String, data:String, senderContext:Any) = {

val headers = Map(

Exchange.HTTP_URI -> s"$endpointUri/$resource/$data",

Exchange.HTTP_METHOD -> "GET",

contextHeader -> senderContext

)

CamelMessage("", headers)

}

override def transformResponse(msg: Any) = msg match {

case msg: CamelMessage => msg.headerAs[String](Exchange.HTTP_URI) match {

case Success(cardId) if cardId.contains(cardIdResource) => TokenizeResponse(msg.bodyAs[String], msg.headers(contextHeader))

case Success(cardNumber) if cardNumber.contains(cardNumberResource) => OpenCardResponse(msg.bodyAs[String], msg.headers(contextHeader))

case Success(other) => log.error("Unexpected response {} from Tokenizer", other)

case Failure(e) => log.error(e, "Error received from Tokenizer")

}

case akka.actor.Status.Failure(e) => log.error(e, "Error received from Tokenizer")

}

}

2200 LOC Scala

promedio 100 por archivo

1000 LOC Java (HSM)

promedio 145 por archivo

.jar 300 kb

lib 22 mb

“If I have seen further it is by standing on the shoulders of giants”

akka-testkit

ScalaTest

TeamCity no sabe ejecutar tests de Scala

http://youtrack.jetbrains.com/issue/TW-29678

JMeter

En condiciones preliminares e imperfectas

Ambiente local + Oracle de desarrollo

Flujo simplificado

“Enviando” las transacciones a log por Camel (sin JMS)

Todo con la misma tarjeta

~100 tps

A través del “ManagementReceiver” podemos dinámicamente configurar, bajar, reiniciar canales.

Trivial de hacer con Akka

Metrics de @coda

Además enviamos status a través del "ManagementSender"