Skip to content

Commit

Permalink
Twilio Trunk Provision
Browse files Browse the repository at this point in the history
  • Loading branch information
docwho2 committed Nov 23, 2023
1 parent 83498e9 commit 0a97e65
Show file tree
Hide file tree
Showing 11 changed files with 228 additions and 177 deletions.
22 changes: 14 additions & 8 deletions src/main/java/cloud/cleo/chimesma/cdk/InfrastructureApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ public enum ENV_VARS {
* If set in the environment, setup Origination to point to Voice Connector and allow from termination as well
*/
PBX_HOSTNAME,
/**
* Provision Twilio SIP Trunk (experimental)
*/
TWILIO,
/**
* Attempt to provision a phone number in this area code (US only and experimental)
*/
Expand All @@ -37,7 +33,13 @@ public enum ENV_VARS {
/**
* Single IP address to allow to call the Voice Connector (Cannot be private range or will fail)
*/
VOICE_CONNECTOR_ALLOW_IP
VOICE_CONNECTOR_ALLOW_IP,

/**
* Twilio Keys, provisions SIP Trunk if both present
*/
TWILIO_ACCOUNT_SID,
TWILIO_AUTH_TOKEN
}

public static void main(final String[] args) {
Expand All @@ -64,13 +66,13 @@ public static void main(final String[] args) {
.env(makeStackEnv(accountId, regionWest))
.build());

if (hasEnv(TWILIO)) {
if (hasTwilio()) {
new TwilioStack(app, "twilio", StackProps.builder()
.description("Provision Twilio Resources")
.description("Provision Twilio Sip Trunk")
.stackName(stackName + "-twilio")
.env(makeStackEnv(accountId, regionEast))
.crossRegionReferences(Boolean.TRUE)
.build(), east.getVCHostName(), west.getVCHostName());
.build(), east.getVoiceConnector(), west.getVoiceConnector());
}

// Provision Chime Phone Number if area code provided
Expand All @@ -88,6 +90,10 @@ public static void main(final String[] args) {

}

public static boolean hasTwilio() {
return hasEnv(TWILIO_ACCOUNT_SID) && hasEnv(TWILIO_AUTH_TOKEN);
}

/**
* Get the value for one of the ENV variables
* @param envVar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public InfrastructureStack(final App app, final String id, final StackProps prop


String vc_arn = "PSTN";
if ( hasEnv(VOICE_CONNECTOR,PBX_HOSTNAME) ) {
if ( hasEnv(VOICE_CONNECTOR,PBX_HOSTNAME,TWILIO_ACCOUNT_SID) ) {

// Voice Connector
vc = new ChimeVoiceConnector(this);
Expand Down Expand Up @@ -98,12 +98,12 @@ public InfrastructureStack(final App app, final String id, final StackProps prop
}

/**
* Voice Connector Host Name
* Voice Connector or null if it was never created
*
* @return
*/
public String getVCHostName() {
return vc == null ? "N/A" : vc.getOutboundName();
public ChimeVoiceConnector getVoiceConnector() {
return vc;
}

/**
Expand Down
20 changes: 12 additions & 8 deletions src/main/java/cloud/cleo/chimesma/cdk/TwilioStack.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
package cloud.cleo.chimesma.cdk;

import cloud.cleo.chimesma.cdk.customresources.ChimeVoiceConnector;
import cloud.cleo.chimesma.cdk.twilio.*;
import software.amazon.awscdk.App;
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;

/**
* CDK Stack
* CDK Stack
*
* @author sjensen
*/
public class TwilioStack extends Stack {


public TwilioStack(final App parent, final String id, String vc1, String vc2) {
this(parent, id, null,vc1,vc2);
public TwilioStack(final App parent, final String id, ChimeVoiceConnector vc1, ChimeVoiceConnector vc2) {
this(parent, id, null, vc1, vc2);
}

public TwilioStack(final Construct parent, final String id, final StackProps props, String vc1, String vc2) {
public TwilioStack(final Construct parent, final String id, final StackProps props, ChimeVoiceConnector vc1, ChimeVoiceConnector vc2) {
super(parent, id, props);

new TwilioSipTrunk(this,vc1, vc2);
new TwilioRule(this);

// Create the Trunk
final var sipTrunk = new TwilioSipTrunk(this);

// Set the Orig entries to the VC's
new TwilioOriginationUrl(this, sipTrunk.getSid(), vc1);
new TwilioOriginationUrl(this, sipTrunk.getSid(), vc2);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import static cloud.cleo.chimesma.cdk.InfrastructureApp.ENV_VARS.*;
import static cloud.cleo.chimesma.cdk.InfrastructureApp.getEnv;
import static cloud.cleo.chimesma.cdk.InfrastructureApp.hasEnv;
import static cloud.cleo.chimesma.cdk.InfrastructureApp.hasTwilio;
import java.util.ArrayList;

/**
Expand All @@ -32,6 +33,8 @@ public class ChimeVoiceConnector extends AwsCustomResource {

private final static String ID = "VC-CR";

private final String region;

/**
* The Voice Connector ID in the API response
*/
Expand All @@ -57,6 +60,8 @@ public ChimeVoiceConnector(Stack scope) {
.logRetention(RetentionDays.ONE_MONTH)
.build());

region = scope.getRegion();

/**
* // Don't enable SIP logging on VC, This can be done manually SIP Logs final var logging = new
* AwsCustomResource(scope, ID + "-LOG", AwsCustomResourceProps.builder()
Expand All @@ -73,7 +78,7 @@ public ChimeVoiceConnector(Stack scope) {
var termAllow = new ArrayList<AclCidr>();

// Add Twilio
if (hasEnv(PBX_HOSTNAME, TWILIO)) {
if (hasEnv(PBX_HOSTNAME) || hasTwilio() ) {
// Start with list of Twilio NA ranges for SIP Trunking
termAllow.add(AclCidr.ipv4("54.172.60.0/30"));
termAllow.add(AclCidr.ipv4("54.244.51.0/30"));
Expand Down Expand Up @@ -145,6 +150,10 @@ public String getArn() {
public String getOutboundName() {
return getResponseField("VoiceConnector.OutboundHostName");
}

public String getRegion() {
return region;
}

/**
* Required parameters for the CreateVoiceConnectorCommand API call
Expand Down
21 changes: 14 additions & 7 deletions src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.Arrays;
import static java.util.Collections.singletonList;
import java.util.List;
import java.util.Map;
import software.amazon.awscdk.BundlingOptions;
import software.amazon.awscdk.BundlingOutput;
import software.amazon.awscdk.DockerVolume;
Expand All @@ -18,6 +19,9 @@
import static software.amazon.awscdk.services.lambda.Runtime.*;
import software.amazon.awscdk.services.logs.RetentionDays;
import software.amazon.awscdk.services.s3.assets.AssetOptions;
import static cloud.cleo.chimesma.cdk.InfrastructureApp.ENV_VARS.*;
import cloud.cleo.chimesma.cdk.InfrastructureApp;
import java.util.concurrent.atomic.AtomicInteger;

/**
* Base class for all Twilio Custom Resource Lambda's
Expand All @@ -26,16 +30,16 @@
*/
public abstract class TwilioBase extends Function {


private static final AtomicInteger ID_COUNTER = new AtomicInteger(0);
private static final BundlingOptions builderOptions;

static {
List<String> functionOnePackagingInstructions = Arrays.asList(
"/bin/sh",
"-c",
"mvn clean install && cp /asset-input/target/twilio.jar /asset-output/");
"mvn clean install && cp /asset-input/target/twilio.jar /asset-output/");

builderOptions = BundlingOptions.builder()
builderOptions = BundlingOptions.builder()
.command(functionOnePackagingInstructions)
.image(JAVA_17.getBundlingImage())
.user("root")
Expand All @@ -48,25 +52,28 @@ public abstract class TwilioBase extends Function {
* @param scope
*/
protected TwilioBase(Stack scope, Class c) {
super(scope, c.getSimpleName(), FunctionProps.builder()
super(scope, c.getSimpleName() + ID_COUNTER.incrementAndGet(), FunctionProps.builder()
.handler(c.getName())
.runtime(JAVA_17)
.description(c.getSimpleName() + " Provisioning Lambda")
.timeout(Duration.seconds(30))
.logRetention(RetentionDays.ONE_MONTH)
.maxEventAge(Duration.seconds(60))
.timeout(Duration.seconds(30))
.timeout(Duration.minutes(5))
.retryAttempts(0)
.memorySize(512)
.code(getCode())
.environment(Map.of(TWILIO_ACCOUNT_SID.toString(), InfrastructureApp.getEnv(TWILIO_ACCOUNT_SID),
TWILIO_AUTH_TOKEN.toString(), InfrastructureApp.getEnv(TWILIO_AUTH_TOKEN)))
.build());


}

protected static Code getCode() {
return Code.fromAsset("./twilio", AssetOptions.builder()
.bundling(builderOptions).build());
}

public abstract String getSid();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package cloud.cleo.chimesma.cdk.twilio;

import cloud.cleo.chimesma.cdk.customresources.ChimeVoiceConnector;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import software.amazon.awscdk.CustomResource;
import software.amazon.awscdk.CustomResourceProps;
import software.amazon.awscdk.Stack;

/**
* Twilio SIP Trunk Function that will provision
*
* @author sjensen
*/
public class TwilioOriginationUrl extends TwilioBase {

private static final AtomicInteger ID_COUNTER = new AtomicInteger(0);
final CustomResource cr;

/**
* @param scope
* @param trunkSid
* @param vc
*/
public TwilioOriginationUrl(Stack scope, String trunkSid, ChimeVoiceConnector vc) {
super(scope, TwilioOriginationUrl.class);

// Add associated Custom Resource linked to this Lambda
cr = new CustomResource(this, "SipOrigUrlResource"+ ID_COUNTER.incrementAndGet(), CustomResourceProps.builder()
.resourceType("Custom::" + TwilioOriginationUrl.class.getSimpleName())
.properties(Map.of("trunkSid", trunkSid, "voiceConnector", vc.getOutboundName(),"region",vc.getRegion()))
.serviceToken(getFunctionArn())
.build());

}

@Override
public String getSid() {
return cr.getRef();
}
}
35 changes: 0 additions & 35 deletions src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioRule.java

This file was deleted.

13 changes: 8 additions & 5 deletions src/main/java/cloud/cleo/chimesma/cdk/twilio/TwilioSipTrunk.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
*/
package cloud.cleo.chimesma.cdk.twilio;

import java.util.Map;
import software.amazon.awscdk.CustomResource;
import software.amazon.awscdk.CustomResourceProps;
import software.amazon.awscdk.Stack;
Expand All @@ -16,21 +15,25 @@
*/
public class TwilioSipTrunk extends TwilioBase {

final CustomResource cr;

/**
* @param scope
*/
public TwilioSipTrunk(Stack scope, String vc1, String vc2) {
public TwilioSipTrunk(Stack scope) {
super(scope, TwilioSipTrunk.class);

// Add associated Custom Resource linked to this Lambda
new CustomResource(this, "SipTrunkResource", CustomResourceProps.builder()
cr = new CustomResource(this, "SipTrunkResource", CustomResourceProps.builder()
.resourceType("Custom::" + TwilioSipTrunk.class.getSimpleName())
.properties(Map.of("vcEast",vc1,"vcWest",vc2,"vcEastRegion","us-east-1","vcWestRegion","us-east-2"))
.serviceToken(getFunctionArn())
.build());

}


@Override
public String getSid() {
return cr.getRef();
}

}
Loading

0 comments on commit 0a97e65

Please sign in to comment.