diff --git a/apps/dashboard/pom.xml b/apps/dashboard/pom.xml
index afcbf4894f..e6b3945585 100644
--- a/apps/dashboard/pom.xml
+++ b/apps/dashboard/pom.xml
@@ -51,6 +51,21 @@
aws-java-sdk-autoscaling
1.12.405
+
+ com.amazonaws
+ aws-java-sdk-ec2
+ 1.12.405
+
+
+ com.amazonaws
+ aws-java-sdk-sts
+ 1.12.405
+
+
+ com.amazonaws
+ aws-java-sdk-iam
+ 1.12.405
+
org.apache.struts
struts2-core
diff --git a/apps/dashboard/src/main/java/com/akto/action/quick_start/QuickStartAction.java b/apps/dashboard/src/main/java/com/akto/action/quick_start/QuickStartAction.java
index b8ccb88a14..e89283b49b 100644
--- a/apps/dashboard/src/main/java/com/akto/action/quick_start/QuickStartAction.java
+++ b/apps/dashboard/src/main/java/com/akto/action/quick_start/QuickStartAction.java
@@ -3,6 +3,7 @@
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.net.InetAddress;
import java.util.*;
import java.util.concurrent.*;
@@ -11,11 +12,11 @@
import com.akto.utils.platform.DashboardStackDetails;
import com.akto.utils.platform.MirroringStackDetails;
import com.akto.utils.cloud.stack.dto.StackState;
-import com.amazonaws.services.cloudformation.model.Tag;
+import com.amazonaws.services.cloudformation.AmazonCloudFormation;
+import com.amazonaws.services.cloudformation.AmazonCloudFormationClientBuilder;
+import com.amazonaws.services.cloudformation.model.*;
import org.apache.commons.lang3.StringUtils;
import org.bson.conversions.Bson;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import com.akto.action.UserAction;
import com.akto.dao.ApiTokensDao;
@@ -60,6 +61,28 @@ public class QuickStartAction extends UserAction {
private String aktoDashboardStackName;
+ private DeploymentMethod deploymentMethod;
+
+ private String aktoNLBIp;
+ private String aktoMongoConn;
+
+ public enum DeploymentMethod {
+ AWS_TRAFFIC_MIRRORING,
+ KUBERNETES;
+
+ public DeploymentMethod getDeploymentMethod(String deploymentMethod) {
+ if (StringUtils.isEmpty(deploymentMethod)) {
+ return AWS_TRAFFIC_MIRRORING;
+ }
+ for (DeploymentMethod method : DeploymentMethod.values()) {
+ if (method.name().equalsIgnoreCase(deploymentMethod)) {
+ return method;
+ }
+ }
+ return null;
+ }
+ }
+
private static final LoggerMaker loggerMaker = new LoggerMaker(QuickStartAction.class);
@@ -87,6 +110,9 @@ public String fetchQuickStartPageState() {
}
public String fetchLoadBalancers() {
+ if(deploymentMethod != null && deploymentMethod.equals(DeploymentMethod.KUBERNETES)) {
+ return handleKubernetes();
+ }
List availableLBs = new ArrayList<>();
List selectedLBs = new ArrayList<>();
ExecutorService executorService = Executors.newFixedThreadPool(3);
@@ -135,6 +161,52 @@ public String fetchLoadBalancers() {
return Action.SUCCESS.toUpperCase();
}
+ private String handleKubernetes(){
+ try {
+ DescribeStackResourcesRequest req = new DescribeStackResourcesRequest();
+ req.setStackName(MirroringStackDetails.getStackName());
+ req.setLogicalResourceId(MirroringStackDetails.AKTO_NLB);
+ AmazonCloudFormation cloudFormation = AmazonCloudFormationClientBuilder.standard()
+ .build();
+ cloudFormation.describeStackResources(req);
+ this.dashboardHasNecessaryRole = true;
+ } catch (Exception e){ // TODO: Handle specific exception
+ if(e.getMessage().contains("not authorized")){
+ this.dashboardHasNecessaryRole = false;
+ } else{
+ this.dashboardHasNecessaryRole = true;
+ }
+ }
+ this.awsRegion = System.getenv(Constants.AWS_REGION);
+ this.awsAccountId = System.getenv(Constants.AWS_ACCOUNT_ID);
+ this.aktoMirroringStackName = MirroringStackDetails.getStackName();
+ this.aktoDashboardStackName = DashboardStackDetails.getStackName();
+ this.aktoDashboardRoleName = DashboardStackDetails.getAktoDashboardRole();
+
+ return Action.SUCCESS.toUpperCase();
+ }
+
+ public String createKubernetesStack(){
+ if (!AwsStack.getInstance().checkIfStackExists(MirroringStackDetails.getStackName())) {
+ try {
+ Map parameters = new HashMap<>();
+ parameters.put("MongoIp", System.getenv("AKTO_MONGO_CONN"));
+ parameters.put("KeyPair", System.getenv("EC2_KEY_PAIR"));
+ parameters.put("SubnetId", System.getenv("EC2_SUBNET_ID"));
+ String template = convertStreamToString(AwsStack.class
+ .getResourceAsStream("/cloud_formation_templates/kubernetes_mirroring.template"));
+ List tags = Utils.fetchTags(DashboardStackDetails.getStackName());
+ String stackId = AwsStack.getInstance().createStack(MirroringStackDetails.getStackName(), parameters, template, tags);
+ loggerMaker.infoAndAddToDb(String.format("Stack %s creation started successfully", stackId), LogDb.DASHBOARD);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else {
+ throw new RuntimeException("Akto mirroring setup is complete!!");
+ }
+ return Action.SUCCESS.toUpperCase();
+ }
+
private String filterLBName(String lbArn) {
if(StringUtils.isEmpty(lbArn)){
return "";
@@ -215,6 +287,12 @@ public String checkStackCreationProgress() {
loggerMaker.infoAndAddToDb("Nothing set in DB, moving on", LogDb.DASHBOARD);
}
}
+ if(DeploymentMethod.KUBERNETES.equals(this.deploymentMethod) && Stack.StackStatus.CREATE_COMPLETE.toString().equals(this.stackState.getStatus())){
+ loggerMaker.infoAndAddToDb("Stack creation complete, fetching outputs", LogDb.DASHBOARD);
+ Map outputsMap = Utils.fetchOutputs(MirroringStackDetails.getStackName());
+ this.aktoNLBIp = outputsMap.get("AktoNLB");
+ this.aktoMongoConn = System.getenv("AKTO_MONGO_CONN");
+ }
return Action.SUCCESS.toUpperCase();
}
@@ -342,4 +420,28 @@ private static String convertStreamToString(InputStream in) throws Exception {
in.close();
return stringbuilder.toString();
}
+
+ public DeploymentMethod getDeploymentMethod() {
+ return deploymentMethod;
+ }
+
+ public void setDeploymentMethod(DeploymentMethod deploymentMethod) {
+ this.deploymentMethod = deploymentMethod;
+ }
+
+ public String getAktoNLBIp() {
+ return aktoNLBIp;
+ }
+
+ public void setAktoNLBIp(String aktoNLBIp) {
+ this.aktoNLBIp = aktoNLBIp;
+ }
+
+ public String getAktoMongoConn() {
+ return aktoMongoConn;
+ }
+
+ public void setAktoMongoConn(String aktoMongoConn) {
+ this.aktoMongoConn = aktoMongoConn;
+ }
}
\ No newline at end of file
diff --git a/apps/dashboard/src/main/java/com/akto/utils/cloud/Utils.java b/apps/dashboard/src/main/java/com/akto/utils/cloud/Utils.java
index 45e8ef4d35..194d662e08 100644
--- a/apps/dashboard/src/main/java/com/akto/utils/cloud/Utils.java
+++ b/apps/dashboard/src/main/java/com/akto/utils/cloud/Utils.java
@@ -2,13 +2,13 @@
import com.amazonaws.services.cloudformation.AmazonCloudFormation;
import com.amazonaws.services.cloudformation.AmazonCloudFormationClientBuilder;
-import com.amazonaws.services.cloudformation.model.DescribeStacksRequest;
-import com.amazonaws.services.cloudformation.model.DescribeStacksResult;
-import com.amazonaws.services.cloudformation.model.Tag;
+import com.amazonaws.services.cloudformation.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
public class Utils {
@@ -21,13 +21,23 @@ public static CloudType getCloudType() {
}
public static List fetchTags(String stackName){
+ Stack stack = fetchStack(stackName);
+ return stack.getTags();
+ }
+
+ private static Stack fetchStack(String stackName) {
DescribeStacksRequest describeStackRequest = new DescribeStacksRequest();
describeStackRequest.setStackName(stackName);
AmazonCloudFormation cloudFormation = AmazonCloudFormationClientBuilder.standard()
.build();
DescribeStacksResult result = cloudFormation.describeStacks(describeStackRequest);
- com.amazonaws.services.cloudformation.model.Stack stack = result.getStacks().get(0);
- return stack.getTags();
+ Stack stack = result.getStacks().get(0);
+ return stack;
+ }
+
+ public static Map fetchOutputs(String stackName){
+ Stack stack = fetchStack(stackName);
+ return stack.getOutputs().stream().collect(Collectors.toMap(Output::getOutputKey, Output::getOutputValue));
}
}
diff --git a/apps/dashboard/src/main/resources/cloud_formation_templates/kubernetes_mirroring.template b/apps/dashboard/src/main/resources/cloud_formation_templates/kubernetes_mirroring.template
new file mode 100644
index 0000000000..2ba227a628
--- /dev/null
+++ b/apps/dashboard/src/main/resources/cloud_formation_templates/kubernetes_mirroring.template
@@ -0,0 +1,808 @@
+{
+ "AWSTemplateFormatVersion": "2010-09-09",
+ "Description": "This template does a simple setup for all Akto modules. It sets up all modules on a single instance. If you want a scalable and flexible setup, please contact support@akto.io.",
+ "Parameters": {
+ "SubnetId": {
+ "Type": "AWS::EC2::Subnet::Id"
+ },
+ "KeyPair": {
+ "Type": "AWS::EC2::KeyPair::KeyName"
+ },
+ "MongoIp": {
+ "Type": "String"
+ }
+ },
+ "Mappings": {
+ "RegionMap": {
+ "af-south-1": {
+ "AMI": "ami-0adee70ff4394e3d5"
+ },
+ "eu-north-1": {
+ "AMI": "ami-04e8b0e36ed3403dc"
+ },
+ "ap-south-1": {
+ "AMI": "ami-09de362f44ba0a166"
+ },
+ "eu-west-3": {
+ "AMI": "ami-0614433a16ab15878"
+ },
+ "eu-west-2": {
+ "AMI": "ami-030770b178fa9d374"
+ },
+ "eu-south-1": {
+ "AMI": "ami-0432f14b68c3e0273"
+ },
+ "eu-west-1": {
+ "AMI": "ami-0bba0a4cb75835f71"
+ },
+ "ap-northeast-3": {
+ "AMI": "ami-0253beba286f3e848"
+ },
+ "ap-northeast-2": {
+ "AMI": "ami-0e1d09d8b7c751816"
+ },
+ "me-south-1": {
+ "AMI": "ami-07a68e42e669daed0"
+ },
+ "ap-northeast-1": {
+ "AMI": "ami-06ce6680729711877"
+ },
+ "sa-east-1": {
+ "AMI": "ami-0656df2cc0dfd150a"
+ },
+ "ca-central-1": {
+ "AMI": "ami-04c12937e87474def"
+ },
+ "ap-east-1": {
+ "AMI": "ami-0b751f901b93720a5"
+ },
+ "ap-southeast-1": {
+ "AMI": "ami-0adf622550366ea53"
+ },
+ "ap-southeast-2": {
+ "AMI": "ami-03b836d87d294e89e"
+ },
+ "eu-central-1": {
+ "AMI": "ami-094c442a8e9a67935"
+ },
+ "ap-southeast-3": {
+ "AMI": "ami-0483d92a8124da6c9"
+ },
+ "us-east-1": {
+ "AMI": "ami-065efef2c739d613b"
+ },
+ "us-east-2": {
+ "AMI": "ami-07251f912d2a831a3"
+ },
+ "us-west-1": {
+ "AMI": "ami-09b2f6d85764ec71b"
+ },
+ "us-west-2": {
+ "AMI": "ami-0d08ef957f0e4722b"
+ }
+ }
+ },
+ "Resources": {
+ "GetAktoSetupDetailsLambdaBasicExecutionRole": {
+ "Type": "AWS::IAM::Role",
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "lambda.amazonaws.com"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+ },
+ "Path": "/",
+ "Policies": [
+ {
+ "PolicyName": "GetAktoSetupDetailsExecuteLambda",
+ "PolicyDocument": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "ec2:DescribeNetworkInterfaces",
+ "ec2:DescribeTrafficMirrorSessions",
+ "ec2:DescribeInstances",
+ "ec2:DescribeVpcs",
+ "elasticloadbalancing:DescribeLoadBalancers",
+ "elasticloadbalancing:DescribeTargetGroups",
+ "elasticloadbalancing:DescribeTargetHealth"
+ ],
+ "Resource": "*"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ "GetAktoSetupDetails": {
+ "Type": "AWS::Lambda::Function",
+ "Properties": {
+ "Runtime": "nodejs12.x",
+ "Timeout": 60,
+ "Role": {
+ "Fn::GetAtt": [
+ "GetAktoSetupDetailsLambdaBasicExecutionRole",
+ "Arn"
+ ]
+ },
+ "Handler": "index.handler",
+ "Environment": {
+ "Variables": {
+ "TARGET_LB": {
+ "Ref": "AktoNLB"
+ }
+ }
+ },
+ "Code": {
+ "S3Bucket": {
+ "Fn::Sub": "akto-setup-${AWS::Region}"
+ },
+ "S3Key": "templates/get-akto-setup-details.zip"
+ }
+ }
+ },
+ "GetVpcDetailsLambdaRole": {
+ "Type": "AWS::IAM::Role",
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": [
+ "lambda.amazonaws.com"
+ ]
+ },
+ "Action": [
+ "sts:AssumeRole"
+ ]
+ }
+ ]
+ },
+ "Path": "/",
+ "Policies": [
+ {
+ "PolicyName": "DescribeAssetsPolicy",
+ "PolicyDocument": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "ec2:DescribeVpcs",
+ "ec2:DescribeSubnets"
+ ],
+ "Resource": "*"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ "GetVpcDetailsLambda": {
+ "Type": "AWS::Lambda::Function",
+ "Properties": {
+ "Description": "Look up info from a VPC",
+ "Handler": "index.handler",
+ "Runtime": "nodejs12.x",
+ "Timeout": 30,
+ "Role": {
+ "Fn::GetAtt": [
+ "GetVpcDetailsLambdaRole",
+ "Arn"
+ ]
+ },
+ "Environment": {
+ "Variables": {
+ "SUBNET_ID": {
+ "Ref": "SubnetId"
+ }
+ }
+ },
+ "Code": {
+ "ZipFile": "var SUBNET_ID = process.env.SUBNET_ID; var aws = require('aws-sdk'); var response = require('cfn-response'); var ec2 = new aws.EC2(); exports.handler = async function(event, context) {\n if (event.RequestType == 'Delete') {\n await response.send(event, context, 'SUCCESS');\n return;\n }\n var params = {\n SubnetIds: [SUBNET_ID] \n };\n var subnets = await ec2.describeSubnets(params).promise().catch(err => {\n console.error(err);\n });\n var vpcId = subnets['Subnets'][0]['VpcId'];\n var vpcs = await ec2.describeVpcs({VpcIds: [vpcId]}).promise().catch(err => {\n console.error(err);\n });\n await response.send(event, context, 'SUCCESS', {CidrBlock: vpcs['Vpcs'][0]['CidrBlock'], VpcId: vpcId})\n};\n"
+ }
+ }
+ },
+ "CustomSourceGetVpcDetails": {
+ "Type": "AWS::CloudFormation::CustomResource",
+ "Properties": {
+ "ServiceToken": {
+ "Fn::GetAtt": [
+ "GetVpcDetailsLambda",
+ "Arn"
+ ]
+ }
+ }
+ },
+ "IamInstanceProfile": {
+ "Type": "AWS::IAM::InstanceProfile",
+ "Properties": {
+ "Path": "/",
+ "Roles": [
+ {
+ "Ref": "RefreshHandlerLambdaBasicExecutionRole"
+ }
+ ]
+ }
+ },
+ "AktoContextAnalyzerSecurityGroup": {
+ "Type": "AWS::EC2::SecurityGroup",
+ "Properties": {
+ "VpcId": {
+ "Fn::GetAtt": [
+ "CustomSourceGetVpcDetails",
+ "VpcId"
+ ]
+ },
+ "GroupDescription": "Enable the ports Akto requires (22, 9092)",
+ "SecurityGroupIngress": [
+ {
+ "IpProtocol": "tcp",
+ "FromPort": 22,
+ "ToPort": 22,
+ "CidrIp": {
+ "Fn::GetAtt": [
+ "CustomSourceGetVpcDetails",
+ "CidrBlock"
+ ]
+ }
+ },
+ {
+ "IpProtocol": "tcp",
+ "FromPort": 9092,
+ "ToPort": 9092,
+ "CidrIp": {
+ "Fn::GetAtt": [
+ "CustomSourceGetVpcDetails",
+ "CidrBlock"
+ ]
+ }
+ }
+ ],
+ "SecurityGroupEgress": []
+ }
+ },
+ "AktoContextAnalyzerASGLaunchConfiguration": {
+ "Type": "AWS::AutoScaling::LaunchConfiguration",
+ "Properties": {
+ "ImageId": {
+ "Fn::FindInMap": [
+ "RegionMap",
+ {
+ "Ref": "AWS::Region"
+ },
+ "AMI"
+ ]
+ },
+ "InstanceType": "m5a.xlarge",
+ "KeyName": {
+ "Ref": "KeyPair"
+ },
+ "AssociatePublicIpAddress": "false",
+ "SecurityGroups": [
+ {
+ "Ref": "AktoContextAnalyzerSecurityGroup"
+ }
+ ],
+ "BlockDeviceMappings": [
+ {
+ "DeviceName": "/dev/xvda",
+ "Ebs": {
+ "VolumeType": "gp2",
+ "DeleteOnTermination": "true",
+ "VolumeSize": "50",
+ "Encrypted": true
+ }
+ }
+ ],
+ "MetadataOptions": {
+ "HttpTokens": "required"
+ },
+ "UserData": {
+ "Fn::Base64": {
+ "Fn::Join": [
+ "\n",
+ [
+ "#!/bin/bash -xe",
+ {
+ "Fn::Sub": "export AKTO_MONGO_CONN='${MongoIp}'"
+ },
+ "touch /tmp/hello.txt",
+ "touch ~/hello.txt",
+ "sudo yum update -y",
+ "sudo yum install -y python python-setuptools",
+ "sudo yum install -y docker",
+ "sudo dockerd&",
+ "sudo mkdir -p /opt/aws/bin",
+ "export COMPOSE_FILE=docker-compose-context-analyser.yml",
+ "sudo wget https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz",
+ "sudo python -m easy_install --script-dir /opt/aws/bin aws-cfn-bootstrap-latest.tar.gz",
+ "curl -fsSL 'https://raw.githubusercontent.com/akto-api-security/infra/feature/segregation_2/cf-deploy-akto' > cf-deploy-akto",
+ "sudo chmod 700 cf-deploy-akto",
+ "./cf-deploy-akto < <(echo 'test')",
+ "sudo echo >> ~/akto/infra/docker-context-analyser.env",
+ "sudo echo AKTO_MONGO_CONN=$AKTO_MONGO_CONN >> ~/akto/infra/docker-context-analyser.env",
+ "export TOKEN=$(curl -X PUT 'http://169.254.169.254/latest/api/token' -H 'X-aws-ec2-metadata-token-ttl-seconds: 600')",
+ {
+ "Fn::Join": [
+ ":",
+ [
+ "export AKTO_CURRENT_INSTANCE_IP=$(curl -H \"X-aws-ec2-metadata-token",
+ "$TOKEN\" -v http://169.254.169.254/latest/meta-data/local-ipv4)"
+ ]
+ ]
+ },
+ "echo AKTO_CURRENT_INSTANCE_IP=$AKTO_CURRENT_INSTANCE_IP >> ~/akto/infra/docker-context-analyser.env",
+ "curl -fsSL 'https://raw.githubusercontent.com/akto-api-security/infra/feature/segregation_2/cf-deploy-akto-start' > cf-deploy-akto-start",
+ "sudo chmod 700 cf-deploy-akto-start",
+ "./cf-deploy-akto-start < <(echo 'test')"
+ ]
+ ]
+ }
+ }
+ }
+ },
+ "AktoContextAnalyzerAutoScalingGroup": {
+ "Type": "AWS::AutoScaling::AutoScalingGroup",
+ "Properties": {
+ "LaunchConfigurationName": {
+ "Ref": "AktoContextAnalyzerASGLaunchConfiguration"
+ },
+ "VPCZoneIdentifier": [
+ {
+ "Ref": "SubnetId"
+ }
+ ],
+ "MaxSize": "1",
+ "MinSize": "1"
+ }
+ },
+ "AktoContextAnalyzerInstanceRefreshHandler": {
+ "Type": "AWS::Lambda::Function",
+ "Properties": {
+ "Handler": "index.handler",
+ "Runtime": "nodejs12.x",
+ "Timeout": 30,
+ "Role": {
+ "Fn::GetAtt": [
+ "InstanceRefreshHandlerLambdaRole",
+ "Arn"
+ ]
+ },
+ "Code": {
+ "ZipFile": "var aws = require('aws-sdk'); var autoscaling = new aws.AutoScaling(); exports.handler = function(event, context) {\n var params = {\n AutoScalingGroupName: 'AktoContextAnalyzerAutoScalingGroup', \n Preferences: {\n InstanceWarmup: 200, \n MinHealthyPercentage: 0\n }\n };\n \n autoscaling.startInstanceRefresh(params, function(err, data) {\n if(err) { console.log(err) }\n else { console.log(data) }\n })\n}; \n"
+ }
+ }
+ },
+ "RefreshHandlerLambdaBasicExecutionRole": {
+ "Type": "AWS::IAM::Role",
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": "ec2.amazonaws.com"
+ },
+ "Action": "sts:AssumeRole"
+ }
+ ]
+ },
+ "Policies": [
+ {
+ "PolicyName": "InvokeLambdaPolicy",
+ "PolicyDocument": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Resource": [
+ {
+ "Fn::GetAtt": [
+ "DashboardInstanceRefreshHandler",
+ "Arn"
+ ]
+ },
+ {
+ "Fn::GetAtt": [
+ "TrafficMirroringInstanceRefreshHandler",
+ "Arn"
+ ]
+ },
+ {
+ "Fn::GetAtt": [
+ "AktoContextAnalyzerInstanceRefreshHandler",
+ "Arn"
+ ]
+ }
+ ],
+ "Action": "lambda:InvokeFunction"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ "AktoSecurityGroup": {
+ "Type": "AWS::EC2::SecurityGroup",
+ "Properties": {
+ "VpcId": {
+ "Fn::GetAtt": [
+ "CustomSourceGetVpcDetails",
+ "VpcId"
+ ]
+ },
+ "GroupDescription": "Enable the ports Akto requires (22, 4789, 8000, 9092)",
+ "SecurityGroupIngress": [
+ {
+ "IpProtocol": "tcp",
+ "FromPort": 22,
+ "ToPort": 22,
+ "CidrIp": {
+ "Fn::GetAtt": [
+ "CustomSourceGetVpcDetails",
+ "CidrBlock"
+ ]
+ }
+ },
+ {
+ "IpProtocol": "tcp",
+ "FromPort": 9092,
+ "ToPort": 9092,
+ "CidrIp": {
+ "Fn::GetAtt": [
+ "CustomSourceGetVpcDetails",
+ "CidrBlock"
+ ]
+ }
+ },
+ {
+ "IpProtocol": "udp",
+ "FromPort": 4789,
+ "ToPort": 4789,
+ "CidrIp": {
+ "Fn::GetAtt": [
+ "CustomSourceGetVpcDetails",
+ "CidrBlock"
+ ]
+ }
+ },
+ {
+ "IpProtocol": "tcp",
+ "FromPort": 8000,
+ "ToPort": 8000,
+ "CidrIp": {
+ "Fn::GetAtt": [
+ "CustomSourceGetVpcDetails",
+ "CidrBlock"
+ ]
+ }
+ }
+ ],
+ "SecurityGroupEgress": []
+ }
+ },
+ "AktoASGLaunchConfiguration": {
+ "Type": "AWS::AutoScaling::LaunchConfiguration",
+ "DependsOn": [
+ "AktoNLB"
+ ],
+ "Properties": {
+ "ImageId": {
+ "Fn::FindInMap": [
+ "RegionMap",
+ {
+ "Ref": "AWS::Region"
+ },
+ "AMI"
+ ]
+ },
+ "InstanceType": "m5a.xlarge",
+ "KeyName": {
+ "Ref": "KeyPair"
+ },
+ "AssociatePublicIpAddress": "false",
+ "IamInstanceProfile": {
+ "Ref": "IamInstanceProfile"
+ },
+ "SecurityGroups": [
+ {
+ "Ref": "AktoSecurityGroup"
+ }
+ ],
+ "BlockDeviceMappings": [
+ {
+ "DeviceName": "/dev/xvda",
+ "Ebs": {
+ "VolumeType": "gp2",
+ "DeleteOnTermination": "true",
+ "VolumeSize": "50",
+ "Encrypted": true
+ }
+ }
+ ],
+ "MetadataOptions": {
+ "HttpTokens": "required"
+ },
+ "UserData": {
+ "Fn::Base64": {
+ "Fn::Join": [
+ "\n",
+ [
+ "#!/bin/bash -xe",
+ {
+ "Fn::Sub": "export AKTO_MONGO_CONN='${MongoIp}'"
+ },
+ {
+ "Fn::Sub": "export AKTO_KAFKA_IP='${AktoNLB.DNSName}'"
+ },
+ "touch /tmp/hello.txt",
+ "touch ~/hello.txt",
+ "sudo yum update -y",
+ "sudo yum install -y python python-setuptools",
+ "sudo yum install -y docker",
+ "sudo dockerd&",
+ "sudo mkdir -p /opt/aws/bin",
+ "export COMPOSE_FILE=docker-compose-runtime.yml",
+ "sudo wget https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz",
+ "sudo python -m easy_install --script-dir /opt/aws/bin aws-cfn-bootstrap-latest.tar.gz",
+ "curl -fsSL 'https://raw.githubusercontent.com/akto-api-security/infra/feature/segregation_2/cf-deploy-akto' > cf-deploy-akto",
+ "sudo chmod 700 cf-deploy-akto",
+ "./cf-deploy-akto < <(echo 'test')",
+ "sudo echo >> ~/akto/infra/docker-runtime.env",
+ "sudo echo AKTO_MONGO_CONN=$AKTO_MONGO_CONN >> ~/akto/infra/docker-runtime.env",
+ "sudo echo AKTO_KAFKA_IP=$AKTO_KAFKA_IP >> ~/akto/infra/.env",
+ "curl -fsSL 'https://raw.githubusercontent.com/akto-api-security/infra/feature/segregation_2/cf-deploy-akto-start' > cf-deploy-akto-start",
+ "sudo chmod 700 cf-deploy-akto-start",
+ "./cf-deploy-akto-start < <(echo 'test')"
+ ]
+ ]
+ }
+ }
+ }
+ },
+ "AktoAutoScalingGroup": {
+ "Type": "AWS::AutoScaling::AutoScalingGroup",
+ "Properties": {
+ "LaunchConfigurationName": {
+ "Ref": "AktoASGLaunchConfiguration"
+ },
+ "VPCZoneIdentifier": [
+ {
+ "Ref": "SubnetId"
+ }
+ ],
+ "TargetGroupARNs": [
+ {
+ "Ref": "AktoTrafficMirroringTargetGroup"
+ },
+ {
+ "Ref": "AktoKafkaTargetGroup"
+ }
+ ],
+ "MaxSize": "10",
+ "MinSize": "1"
+ }
+ },
+ "AktoTargetTrackingNetworkPolicy": {
+ "Type": "AWS::AutoScaling::ScalingPolicy",
+ "Properties": {
+ "PolicyType": "TargetTrackingScaling",
+ "AutoScalingGroupName": {
+ "Ref": "AktoAutoScalingGroup"
+ },
+ "EstimatedInstanceWarmup": 30,
+ "TargetTrackingConfiguration": {
+ "PredefinedMetricSpecification": {
+ "PredefinedMetricType": "ASGAverageNetworkIn"
+ },
+ "TargetValue": 200000000
+ }
+ }
+ },
+ "AktoNLB": {
+ "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
+ "Properties": {
+ "Type": "network",
+ "Scheme": "internal",
+ "IpAddressType": "ipv4",
+ "Subnets": [
+ {
+ "Ref": "SubnetId"
+ }
+ ],
+ "LoadBalancerAttributes": [
+ {
+ "Key": "load_balancing.cross_zone.enabled",
+ "Value": "true"
+ }
+ ]
+ }
+ },
+ "AktoTrafficMirroringTargetGroup": {
+ "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
+ "Properties": {
+ "Port": "4789",
+ "Protocol": "UDP",
+ "HealthCheckEnabled": "true",
+ "HealthCheckIntervalSeconds": 10,
+ "HealthCheckPath": "/metrics",
+ "HealthCheckPort": "8000",
+ "HealthCheckProtocol": "HTTP",
+ "HealthCheckTimeoutSeconds": 6,
+ "HealthyThresholdCount": 2,
+ "UnhealthyThresholdCount": 2,
+ "TargetType": "instance",
+ "VpcId": {
+ "Fn::GetAtt": [
+ "CustomSourceGetVpcDetails",
+ "VpcId"
+ ]
+ },
+ "Targets": []
+ }
+ },
+ "AktoKafkaTargetGroup": {
+ "Type": "AWS::ElasticLoadBalancingV2::TargetGroup",
+ "Properties": {
+ "Port": "9092",
+ "Protocol": "TCP",
+ "TargetType": "instance",
+ "HealthCheckEnabled": "true",
+ "HealthCheckIntervalSeconds": 10,
+ "HealthCheckPath": "/metrics",
+ "HealthCheckPort": "8000",
+ "HealthCheckProtocol": "HTTP",
+ "HealthCheckTimeoutSeconds": 6,
+ "HealthyThresholdCount": 2,
+ "UnhealthyThresholdCount": 2,
+ "VpcId": {
+ "Fn::GetAtt": [
+ "CustomSourceGetVpcDetails",
+ "VpcId"
+ ]
+ },
+ "Targets": []
+ }
+ },
+ "AktoKafkaListener": {
+ "Type": "AWS::ElasticLoadBalancingV2::Listener",
+ "Properties": {
+ "LoadBalancerArn": {
+ "Ref": "AktoNLB"
+ },
+ "Port": "9092",
+ "Protocol": "TCP",
+ "DefaultActions": [
+ {
+ "Type": "forward",
+ "TargetGroupArn": {
+ "Ref": "AktoKafkaTargetGroup"
+ }
+ }
+ ]
+ }
+ },
+ "DashboardInstanceRefreshHandler": {
+ "Type": "AWS::Lambda::Function",
+ "Properties": {
+ "Handler": "index.handler",
+ "Runtime": "nodejs12.x",
+ "Timeout": 30,
+ "Role": {
+ "Fn::GetAtt": [
+ "InstanceRefreshHandlerLambdaRole",
+ "Arn"
+ ]
+ },
+ "Code": {
+ "ZipFile": "var aws = require('aws-sdk'); var autoscaling = new aws.AutoScaling(); exports.handler = function(event, context) {\n var params = {\n AutoScalingGroupName: 'AktoDashboardAutoScalingGroup', \n Preferences: {\n InstanceWarmup: 200, \n MinHealthyPercentage: 0\n }\n };\n \n autoscaling.startInstanceRefresh(params, function(err, data) {\n if(err) { console.log(err) }\n else { console.log(data) }\n })\n};\n"
+ }
+ }
+ },
+ "TrafficMirroringInstanceRefreshHandler": {
+ "Type": "AWS::Lambda::Function",
+ "Properties": {
+ "Handler": "index.handler",
+ "Runtime": "nodejs12.x",
+ "Timeout": 30,
+ "Role": {
+ "Fn::GetAtt": [
+ "InstanceRefreshHandlerLambdaRole",
+ "Arn"
+ ]
+ },
+ "Code": {
+ "ZipFile": "var aws = require('aws-sdk'); var autoscaling = new aws.AutoScaling(); exports.handler = function(event, context) {\n var params = {\n AutoScalingGroupName: 'AktoAutoScalingGroup', \n Preferences: {\n InstanceWarmup: 200, \n MinHealthyPercentage: 0\n }\n };\n \n autoscaling.startInstanceRefresh(params, function(err, data) {\n if(err) { console.log(err) }\n else { console.log(data) }\n })\n};\n"
+ }
+ }
+ },
+ "InstanceRefreshHandlerLambdaRole": {
+ "Type": "AWS::IAM::Role",
+ "Properties": {
+ "AssumeRolePolicyDocument": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Principal": {
+ "Service": [
+ "lambda.amazonaws.com"
+ ]
+ },
+ "Action": [
+ "sts:AssumeRole"
+ ]
+ }
+ ]
+ },
+ "Path": "/service-role/",
+ "Policies": [
+ {
+ "PolicyName": "lambdaExecution-DashboardInstanceRefreshHandler",
+ "PolicyDocument": {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": [
+ "logs:CreateLogGroup"
+ ],
+ "Resource": "*"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "logs:CreateLogStream",
+ "logs:PutLogEvents"
+ ],
+ "Resource": "*"
+ },
+ {
+ "Effect": "Allow",
+ "Action": [
+ "autoscaling:StartInstanceRefresh",
+ "autoscaling:Describe*",
+ "autoscaling:UpdateAutoScalingGroup",
+ "ec2:CreateLaunchTemplateVersion",
+ "ec2:DescribeLaunchTemplates",
+ "ec2:RunInstances"
+ ],
+ "Resource": "*"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ },
+ "Outputs": {
+ "AktoNLB": {
+ "Description": "The IP address of the AktoNLB",
+ "Value": {
+ "Fn::GetAtt": [
+ "AktoNLB",
+ "DNSName"
+ ]
+ },
+ "Export": {
+ "Name": "AktoNLBIP"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/apps/dashboard/src/main/resources/struts.xml b/apps/dashboard/src/main/resources/struts.xml
index c8f10a52fb..ea80a53678 100644
--- a/apps/dashboard/src/main/resources/struts.xml
+++ b/apps/dashboard/src/main/resources/struts.xml
@@ -1488,6 +1488,17 @@
+
+
+
+
+
+ 422
+ false
+ ^actionErrors.*
+
+
+
diff --git a/apps/dashboard/web/src/apps/dashboard/shared/icons/k8s.vue b/apps/dashboard/web/src/apps/dashboard/shared/icons/k8s.vue
new file mode 100644
index 0000000000..16cb9b2487
--- /dev/null
+++ b/apps/dashboard/web/src/apps/dashboard/shared/icons/k8s.vue
@@ -0,0 +1,12 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/dashboard/web/src/apps/dashboard/views/quickstart/api.js b/apps/dashboard/web/src/apps/dashboard/views/quickstart/api.js
index 0426630eb5..7dfd6af664 100644
--- a/apps/dashboard/web/src/apps/dashboard/views/quickstart/api.js
+++ b/apps/dashboard/web/src/apps/dashboard/views/quickstart/api.js
@@ -37,11 +37,11 @@ export default{
return resp
})
},
- fetchLBs(){
+ fetchLBs(data){
return request({
url: '/api/fetchLoadBalancers',
method: 'post',
- data: {}
+ data: data
})
},
saveLBs(selectedLBs){
@@ -51,11 +51,11 @@ export default{
data: {selectedLBs}
})
},
- fetchStackCreationStatus(){
+ fetchStackCreationStatus(data){
return request({
url: 'api/checkStackCreationProgress',
method: 'post',
- data: {}
+ data
})
},
getPostmanCredentials() {
@@ -112,5 +112,14 @@ export default{
}).then((resp) => {
return resp
})
+ },
+ createKubernetesStack() {
+ return request({
+ url: '/api/createKubernetesStack',
+ method: 'post',
+ data: {}
+ }).then((resp) => {
+ return resp
+ })
}
}
\ No newline at end of file
diff --git a/apps/dashboard/web/src/apps/dashboard/views/quickstart/components/DataSourcesContent.vue b/apps/dashboard/web/src/apps/dashboard/views/quickstart/components/DataSourcesContent.vue
index e35efc6733..2ff9b54f16 100644
--- a/apps/dashboard/web/src/apps/dashboard/views/quickstart/components/DataSourcesContent.vue
+++ b/apps/dashboard/web/src/apps/dashboard/views/quickstart/components/DataSourcesContent.vue
@@ -21,6 +21,7 @@
+
+
+
diff --git a/apps/dashboard/web/src/apps/dashboard/views/quickstart/components/LoadBalancers.vue b/apps/dashboard/web/src/apps/dashboard/views/quickstart/components/LoadBalancers.vue
index 56e8fd6157..9e0aa27a9b 100644
--- a/apps/dashboard/web/src/apps/dashboard/views/quickstart/components/LoadBalancers.vue
+++ b/apps/dashboard/web/src/apps/dashboard/views/quickstart/components/LoadBalancers.vue
@@ -373,6 +373,7 @@ export default {
],
aktoDashboardRoleName: null,
isLocalDeploy: false,
+ deploymentMethod: "AWS_TRAFFIC_MIRRORING"
}
},
mounted() {
@@ -387,7 +388,7 @@ export default {
this.loading = false;
this.isLocalDeploy = true;
} else {
- api.fetchLBs().then((resp) => {
+ api.fetchLBs({deploymentMethod: this.deploymentMethod}).then((resp) => {
if (!resp.dashboardHasNecessaryRole) {
for (let i = 0; i < this.quick_start_policy_lines.length; i++) {
let line = this.quick_start_policy_lines[i];
@@ -434,7 +435,7 @@ export default {
checkStackState() {
let intervalId = null;
intervalId = setInterval(async () => {
- api.fetchStackCreationStatus().then((resp) => {
+ api.fetchStackCreationStatus({deploymentMethod: this.deploymentMethod}).then((resp) => {
if (this.initialCall) {
this.initialCall = false;
this.loading = false;
diff --git a/apps/dashboard/web/src/plugins/vuetify.js b/apps/dashboard/web/src/plugins/vuetify.js
index 898d04dfe8..d11e3e0920 100644
--- a/apps/dashboard/web/src/plugins/vuetify.js
+++ b/apps/dashboard/web/src/plugins/vuetify.js
@@ -11,6 +11,7 @@ import GithubIcon from "../apps/dashboard/shared/icons/GithubIcon"
import Postman from "../apps/dashboard/shared/icons/Postman"
import AWS from "../apps/dashboard/shared/icons/AWS"
import GCP from "../apps/dashboard/shared/icons/GCP"
+import k8s from '../apps/dashboard/shared/icons/k8s'
import Swagger from "../apps/dashboard/shared/icons/Swagger"
import Restapi from "../apps/dashboard/shared/icons/Restapi"
import CustomWebhooks from "../apps/dashboard/shared/icons/CustomWebhooks"
@@ -222,6 +223,10 @@ faIconsOpts.aws = {
component: AWS
}
+faIconsOpts.k8s = {
+ component: k8s
+}
+
faIconsOpts.swagger = {
component: Swagger
}