-
Notifications
You must be signed in to change notification settings - Fork 1
Build Guide
Mission Control is a Trend game board interface that allows us to create events where participants get hands on experience with Trend Micro products and real-world scenarios in a fun and interactive way.
The purpose of this guide is to provide Challenge Builders with instructions and advice on how to construct a challenge and present it in the game board to a player.
For information on how to word a challenge, please see the Style guide.
The Challenge Builders Core Staff will establish a Teams channel to facilitate communications. You can also coordinate with Core leads if needed but please try to use the channel as much as possible.
Gerald Glasscock – C1 Build Lead
Eric Shulze – V1 Build Lead
Mary Kay Stone – Build Project Manager/Coordinator
Raphael Bottino & Jeff Caten – Build and Integration Specialist
Amanda Veras, Felipe Costa & Nogi Takeru - Code Reviewers
Amanda Veras & Ronald Bautista – Mission Control/Backend Developer
- Objective – In most cases, the Challenge Builders Core Staff will assign you a Trend product or Service they want you to highlight and often a general idea or theme for your challenge. For example, the overall theme for an event might be centered on APIs and you may be asked to create a challenge that requires the player to use our APIs and one of the Cloud One services. When designing your challenge, here are some things to think about:
- What part(s) of the service do we want to highlight? What knowledge do you want the player to walk away with?
- What is a real-life scenario where our customers might use this?
- Think about cool ways to integrate, and demonstrate exciting new features the products have. Think about what you would want to learn, or need to learn, that this task could teach to the field. Tasks should be fun and engaging.
- Tasks – How many steps are needed for the player to complete? If there are several steps needed, you will want to break them up into tasks.
- Scoring – There are 2 ways that you can make sure that a player has completed your challenge. You will need to decide how you want to score your tasks.
- Verify button – This is the preferred method of scoring because it ensures that the player completed all steps and did not guess the answer. The game board has a Verify button option that when a player pushes that button, it will trigger a lambda function that can check that the player has completed the challenge correctly. Verify lambda examples are available in the Github repo. One example of a verify scoring: We've asked the player to enable IPS to defend against an attack. After the player has enabled IPS correctly, the verification lambda can query the console to check to see if IPS is enabled and set to Prevent and the appropriate rule is applied.
Note – A verification lambda cannot accept input from a player.
Note - The Verify button is a real-time user interaction so it has a strict timeout. Verification methods should be sub-second if possible to avoid any timeout issues. Methods such as SSM will take longer than the timeout period which will cause the Verify to fail. Consider using something such as an API call instead.
- Text answer – After your player completes the challenge, you can ask them to enter in an answer of some sort. Text answers are static answers that do not change and will be the same answer for every player. Text answers are not preferable because answers can easily be shared between teams so use this option sparingly.
Keep in mind that you need to pick an answer that is not easily guessed or can be brute forced. For example, you have the player defending against an IPS attack. You can ask them what is the number associated with that IPS rule.
Note - Text answers are inputted into the game board when the challenge is loaded so there is no coding required.
-
Lockout – Some events will have a planned break in the middle for the players. During the planned breaks, we will need to lock players out of the system so they can't work during the break. The Core team will build and execute lockouts. You need to inform the Core team of any infrastructure you think should be locked out. Example: DSM access, security groups, ec2 access, etc.
-
Wrinkles – During the break, we introduce "wrinkles" into the game. Think of the wrinkle as some form of chaos or change that occurs that will cause the player to have to adapt. Wrinkles are examples of what can happen in a real life company. These are normally out of the system administrations/security engineers' control. Not all challenges will have wrinkles but the best ones do. Here are some examples:
- A player has set up IPS on a server to block attacks. No attacks are getting through. But, overnight someone has installed a new piece of software on the server that is vulnerable to attack and there is no IPS rule assigned to prevent it. The player now has to go back and correct the problem.
- The player was instructed to move all servers from his on premise DSM to Workload Security and assign a policy. The next day, the admin sees that one of the build teams built 50 new servers overnight but none of them have a policy assigned. The player now needs to assign policies to all these new servers and set up an event based task to automatically assign a policy to new activations to ensure this doesn't happen again.
- Generic examples of things that could be introduced as a wrinkle are: Blocking access, misconfigured security groups, broken configurations, and attacks - anything indicative of cloud/real-world - that the product can help solve.
In order to ensure that you are pushing your code to the correct branch, we need you to run a setup script before your first push. This script needs to be run locally on your machine and
git config core.hooksPath .githooks
The Mission Control interface will automatically create a new AWS account for every team playing the event. The login credentials for the AWS account will be provided for the player in the Credentials section of the challenge.
If your challenge needs to provide the player with AWS account related information, you can add these in the Outputs of your challenge's main.template.yaml file. Examples of items are: names of AWS items like S3 buckets, SQS/SNS queues or subnets, URLs to directly access an AWS page, SSM details, etc.
Note – Challenges should be built in N. Virginia (us-east1) region of AWS only. When giving the players urls that link directly to AWS assets, please a direct link to N. Virginia.
Players will have limited access to the AWS account that's assigned to them. We do not want them to have unlimited access to view all resources, logs, etc in the account, otherwise they may find ways to cheat in the game. When designing your challenge, please use the principle of least privilege access.
In general, you will need to build any infrastructure inside the AWS account that is needed for your challenge. There are some items though that all players will need or infrastructure that has to be shared amongst builders.
The Core team will provide the following:
- VPC with basic network including private and public subnets
- EKS Cluster
- DSM
To use infrastructure built by main.template.yaml, set those as Parameters in your template.
Any additional infrastructure you need must be built by your template. Some examples of things you may need to build are:
- EC2 instances
- Security Groups
- EKS Nodes – not the cluster, just the nodes
Note – If your challenge requires special networking considerations like an additional subnet or ENI, please discuss with the Core team for approval.
Note – Be wary of any resource limits per account. Example: Default is a limit of 5 Elastic IPs per AWS account.
Note – All EC2 instances need to have an SSM agent installed on them. Amazon Linux 2 and later Windows AMI have it installed by default but please double check.
The zipped code should be pushed to the repo in your challenge's lambda folder. Lambda code must be in an S3 bucket that is the same region as the deploying lambda. We use copyzips to work around this. Copy zips will copy the .zipped code so it can be reached from any region.
This is how you can use copyzips to work around this restriction in your challenge:
utils/sample-usage.template.yaml
Copy this template to your challenge folder, and modify it to copy your .zip file(s).
Service Catalog provisioning and permissions have already been taken care of by templates/service_catalog_portfolio.template.yaml. You do not need to touch this template.
To use Service Catalog in your challenge, pass the values of "PlayerServiceCatalogPortfolio" and "ServiceCatalogLaunchRoleArn" to your challenge's main.template.yaml or day2_main.template.yaml as needed.
Sample code found in your challenge folder's templates/main.template.yaml.
Before you begin building your challenge, the Core team will ask to see the details of what you intend to build. They will be looking for a few things:
- Does the challenge highlight what we want to show about the product/service? Does it fit with the theme of the event, if there is one?
- Is the challenge too long or too short?
- Is it too complicated or too easy?
Day 1: Player needs to upload a file named "test" into an S3 bucket that we've created. We will use a verification lambda to make sure the object has been uploaded successfully.
Day 2: Overnight, we have created a new file in the same S3 bucket and ask the player for a text answer; "what is the name of the new S3 object?"
1 - Clone the entire event repository.
2- Go to the challenges/ folder and make a copy of example_challenge. Name it after the product your challenge is showcasing eg: file_storage_security.
3- We need to build Day 1 first, since Day 2 depends on it. First, edit the templates/main.template.yaml in your newly created challenge folder, to build the necessary resources. In this case, it's just a simple S3 bucket.
4- Now we need to check if the user successfully uploaded the file. In the lambda/verify_lambda_examplefolder of your challenge there are 2 example verification lambdas (one for python and one for javascript). Copy one of those sample lambdas and name it something meaningful. Example: fss_verify.js OR fss_verify.py
You will need to edit the lambda to run a check on the S3 bucket and return a status. In this case, we could list the objects in our S3 bucket and search for a file with the correct name. The results would then be submitted to Mission Control.
5- Copy the code from Github into your own AWS account and run it. Test several scenarios to make sure everything runs as expected. For example, in this case you could test the verify lambda against at least 3 things: test without uploading any files, test with a file that is named incorrect and lastly test with a file that is named correctly.
6 – Once you have completed testing and everything works, you need to "merge" your code with the overall code. This is important because there are typically multiple builders creating challenges and everyone's code will need to work together.
In order for your challenge to be deployed you need to create an entry in the top level templates/main.template.yamlthat will call your challenge. An example entry is located in your challenge folder's templates/main.template.yaml.
This is where you will declare any Parameters or Resources the player may need.
Also add any Outputs you need to provide to the player. Typically Outputs are items related to the player's AWS account such as the name of the S3 bucket and a link to access it.
7- Next we need to assign IAM permissions to the player to allow them access to the AWS resources we created for the challenge. For that, edit the templates/player.template.yaml file. Make sure to include only the required permissions to the player. Challenges should always use the principle of least privilege access and grantonly those privileges needed to complete its task.
8- Test your build using Vending Machine. This will ensure that your challenge builds along with any other challenges and emulates exactly what the player will see the day of the event. (See instructions for Testing below).
Did everything build properly?
Can I login as player, and complete the challenge?
Does player login have required IAM privileges to access the S3 bucket and upload an object?
Are they able to see other S3 buckets or upload to them? Remember, IAM roles need to be least privilege access so the player should not have access to any other AWS objects or resources that aren't part of the challenge.
Troubleshoot and fix until everything builds as expected and the player experience is in the desired state.
9 – Once you are satisfied that your challenge builds correctly and all your tests come back as complete, submit a pull request.
10 - DAY 2 (pretty much same thing with minor changes/additions, so let's work on make sure day 1 looks good first)
You should test your script in your own AWS account using the testDeployment.sh script. To use the script, first you will need to create an S3 bucket in your account and set up AWS CLI on your laptop.
Execute the script on your local machine from the main directory. For example:
./testDeployment.sh BUCKET_NAME STACK_NAME AWS_PROFILE(optional)
This will copy the files from the local folder on your laptop to the S3 bucket you created, then launch the main CloudFormation template and build out your environment.
Any time you push code to Github, your code will automatically be submitted to Linter that will check your code for basic security or configuration issues. We continually to expand its capabilities so that we can eliminate problems with builds.
Before you submit a Pull request, you will want to create your own production-like environment to test in. To do that, click on the Actions tab, then select "Build Dev Environment". Select the drop-down that says "Run Workflow" and enter in the hash commit hash of the code you want to test and click Run Workflow. This will allow you to test your code in an environment that mimics exactly what the player will see.
Where does the code get stored?
The code gets stored in S3, with the exact folder structure you see in the repo. The templates reference the S3 bucket where all code lives as "QSS3BucketName". When testing your own branch before merging, you can store your branch's code in your own S3 bucket and change the QSS3BucketName parameter.
When a branch is merged to main, all code is pushed to the production S3 bucket automatically.
NOTE: Code is stored in an S3 bucket that is not in the same AWS account as the challenge deployment. This may require special considerations in coding, and should always be tested this way.
What if my challenge requires resources outside of the game board or vending machines AWS account?
If your challenge has a resource that lives outside of the game's AWS account, please work with the Core team for solutions. In general, we want everything to be either in our AWS account or a Trend Github. Example, your challenge needs the player to scan code in a GitHub repo.
Can the game be played in any region?
Challenges should be designed to use the N. Virginia (us-east-1) region only. When giving the players urls that link directly to AWS assets, please a direct link to N. Virginia.
When should I submit a pull request?
You should submit a pull request when you’ve completed code that delivers new value BUT does NOT break main. Test all code before submitting a pull request. The smaller the PR, the easier it will be for the Core team to review and approve.
How are Wrinkles introduced? Is it via a stack update or a new stack altogether?
Wrinkles are in a separate template. Examples are available in your challenge folder's template directory. The day2_main.template.yaml in your challenge's template folder is nested into /templates/day2_main.template.yaml off of root. It's deployed by a lambda built in /templates/wrinkles_trigger.template.yaml.
Any resources you want to build on Day 2 should be contained in your challenge folder's /template/day2_main.template.yaml. You then need nest your template into the root /template/day2_main.template.yaml. The /template/wrinkles_trigger.template.yaml builds a lambda which invokes the /templates/day2_main.template.yaml.
Wrinkle Lambda is capable of taking Parameters and Outputs from main.template.yaml (launched day 1), and providing them to day2.main.template.yaml, if you need them. If that's the case, you need to manually edit the Wrinkle lambda to capture the output that you need and provide it as input for the CloudFormation create-stack API call in the function.