├── .gitignore
├── .gitmodules
├── aws
├── custom-remote-state-bucket
│ └── main.tf
├── ec2-redash
│ ├── README.md
│ ├── ec2.tf
│ ├── elastic-ip.tf
│ ├── key_pair.tf
│ ├── outputs.tf
│ ├── providers.tf
│ ├── random.tf
│ ├── sample.png
│ ├── security_group.tf
│ ├── variables.tf
│ └── vpc.tf
├── ec2-simple
│ └── main.tf
├── github-ee
│ ├── dns.tf
│ ├── main.tf
│ ├── security-group.tf
│ └── variables.tf
├── hello-world
│ ├── README.md
│ ├── env0.yml
│ ├── index.template.html
│ ├── main.tf
│ ├── output.tf
│ ├── s3.tf
│ └── sample.png
├── iam
│ └── env0-cost-estimation-role
│ │ ├── README.md
│ │ ├── data.tf
│ │ ├── env0-cost.tf
│ │ ├── outputs.tf
│ │ ├── provider.tf
│ │ ├── variables.tf
│ │ └── versions.tf
├── k8s
│ ├── agent.tf
│ ├── cluster.tf
│ ├── providers.tf
│ ├── variables.tf
│ └── versions.tf
├── opa-example
│ ├── .gitignore
│ ├── README.md
│ ├── env0.yml
│ ├── main.tf
│ ├── tf-lib.rego
│ └── validation.rego
├── profile
│ ├── README.md
│ ├── env0.yml
│ └── main.tf
├── s3-bucket
│ ├── index.html
│ ├── s3
│ │ ├── output.tf
│ │ └── s3.tf
│ ├── tf-0-13
│ │ └── main.tf
│ └── tf-1-0
│ │ └── main.tf
├── security-group
│ ├── README.md
│ ├── provider.tf
│ └── security-group.tf
└── vault-server-on-eks
│ ├── README.md
│ ├── env0.yml
│ ├── get-vault-address.sh
│ ├── main.tf
│ ├── providers.tf
│ ├── variables.tf
│ └── vault-config.yaml
├── azure
├── README.md
├── demo
│ ├── README.md
│ └── main.tf
└── resource-group
│ └── main.tf
├── cloudformation
└── hello-world
│ ├── README.md
│ ├── env0.yml
│ ├── index.template.html
│ ├── sample.png
│ └── stack.yaml
├── community-providers
└── pingdom
│ ├── README.md
│ ├── env0.yml
│ └── main.tf
├── custom-flows
├── external-script.yaml
├── opa-polices
│ └── null-resource.rego
├── opa.yaml
└── scripts
│ └── script.sh
├── gcp
├── bq-dataset
│ ├── README.md
│ └── main.tf
├── container-cluster
│ └── main.tf
└── service-account-key
│ ├── README.md
│ ├── mainf.tf
│ └── variables.tf
├── helm
└── dummy
│ ├── .helmignore
│ ├── Chart.yaml
│ ├── README.md
│ ├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ ├── serviceaccount.yaml
│ └── tests
│ │ └── test-connection.yaml
│ └── values.yaml
├── ibm
└── bare-metal
│ └── main.tf
├── kubernetes
├── hello-world
│ ├── README.md
│ ├── env0.yml
│ └── namespace.yaml
├── squid-proxy
│ ├── README.md
│ ├── env0.yml
│ ├── network-policy.yaml
│ └── squid-proxy.yaml
├── using-pulumi
│ ├── Pulumi.yaml
│ ├── README.md
│ ├── env0.yml
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
└── using-terraform
│ ├── README.md
│ └── main.tf
├── misc
├── ansible
│ └── playbook.yml
├── azure-vault-sensitive-var
│ ├── README.md
│ ├── env0.yml
│ ├── main.tf
│ └── validate.sh
├── clone-with-commit-integ-test
│ ├── env0.yml
│ └── main.tf
├── custom-flow-tf-vars
│ ├── README.md
│ ├── env0.yml
│ └── main.tf
├── custom-flows-environment-variables
│ ├── README.md
│ ├── env0.yml
│ ├── export-user-id.sh
│ ├── main.tf
│ ├── print-user-id.sh
│ └── var-file.json
├── decode-oidc
│ ├── decode-oidc-token.sh
│ ├── env0.yml
│ └── main.tf
├── drift-detection
│ ├── env0.yml
│ └── main.tf
├── ensure-permissions-on-tools-and-folders-for-user-node
│ ├── ensure-permissions.sh
│ ├── env0.yml
│ └── main.tf
├── environment-outputs
│ ├── inputs
│ │ ├── env0.yml
│ │ ├── main.tf
│ │ └── validate.sh
│ └── outputs
│ │ └── main.tf
├── environment-variables
│ ├── README.md
│ ├── env0.yml
│ └── main.tf
├── git-submodules
│ ├── https
│ │ └── README.md
│ └── relative
│ │ └── README.md
├── local-sub-module
│ ├── child
│ │ └── main.tf
│ └── parent
│ │ └── main.tf
├── null-fail-by-variable
│ ├── README.md
│ ├── env0.yml
│ └── main.tf
├── null-resource-with-tf-version-constraints
│ └── main.tf
├── null-resource-workflow-environment
│ ├── README.md
│ └── env0.workflow.yml
├── null-resource
│ └── main.tf
├── null-sleep
│ ├── env0.yml
│ └── main.tf
├── remote-backend-on-s3
│ ├── env0.yml
│ └── main.tf
├── remote-backend
│ ├── env0.yml
│ ├── main.tf
│ └── validate-remote.sh
├── single-environment-workflow
│ ├── README.md
│ └── env0.workflow.yml
├── slack-notification
│ ├── README.md
│ ├── env0.yml
│ ├── main.tf
│ ├── on-approve.sh
│ ├── on-fail.sh
│ ├── on-plan.sh
│ ├── on-start.sh
│ ├── on-store-state.sh
│ ├── on-success.sh
│ └── slack.sh
├── ssm-sensitive-var
│ ├── README.md
│ ├── env0.yml
│ ├── main.tf
│ └── validate.sh
├── terraform-validate-workspace
│ └── main.tf
├── validate-assume-role
│ ├── README.md
│ ├── env0.yml
│ ├── main.tf
│ └── validate.sh
├── validate-state
│ ├── env0.yml
│ ├── main.tf
│ └── validate.sh
├── vault-integration
│ ├── README.md
│ ├── configure-vault.sh
│ ├── env0.yml
│ ├── main.tf
│ └── test-vault.sh
├── workflow-environment-basic-dependencies-2
│ ├── README.md
│ └── env0.workflow.yml
├── workflow-environment-basic-dependencies
│ ├── README.md
│ └── env0.workflow.yml
├── workflow-environment-basic
│ ├── README.md
│ └── env0.workflow.yml
├── workflow-environment
│ ├── README.md
│ └── env0.workflow.yml
├── workflows-with-no-templates
│ └── three-nodes
│ │ └── env0.workflow.yml
└── workflows
│ ├── _init-via-provider_
│ ├── README.md
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
│ ├── environment-alias-validation
│ ├── README.md
│ └── env0.workflow.yml
│ ├── environment-outputs
│ └── env0.workflow.yml
│ ├── graph-with-leaf-dependant-on-two-branches
│ ├── README.md
│ └── env0.workflow.yml
│ └── workflow-with-failures
│ ├── README.md
│ └── env0.workflow.yml
├── plugins
├── checkov
│ ├── env0.yml
│ └── main.tf
├── tflint
│ ├── env0.yml
│ └── main.tf
├── tfsec
│ ├── env0.yml
│ └── main.tf
├── trivy
│ ├── env0.yml
│ └── main.tf
└── v2-spec-file
│ ├── env0.yml
│ └── main.tf
├── pulumi
├── aws
│ └── hello-world
│ │ ├── .gitignore
│ │ ├── Pulumi.dev.yaml
│ │ ├── Pulumi.yaml
│ │ ├── README.md
│ │ ├── env0.yml
│ │ ├── index.template.html
│ │ ├── index.ts
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── sample.png
│ │ ├── tsconfig.json
│ │ └── www
│ │ └── index.html
└── dummy-resource
│ ├── Pulumi.yaml
│ ├── env0.yaml
│ ├── index.ts
│ ├── package-lock.json
│ ├── package.json
│ └── tsconfig.json
├── root-folder-terraform.tf
├── terragrunt
├── __inputs
│ ├── temp.hcl
│ └── temp2.hcl
├── misc
│ ├── ensure-permissions-on-tools-and-folders-for-user-node
│ │ ├── env0.yml
│ │ ├── main.tf
│ │ └── terragrunt.hcl
│ ├── module-resource
│ │ ├── README.md
│ │ ├── module
│ │ │ └── null-module
│ │ │ │ └── main.tf
│ │ ├── simple
│ │ │ └── terragrunt.hcl
│ │ ├── terragrunt.hcl
│ │ └── with-env-yaml
│ │ │ ├── env0.yml
│ │ │ └── terragrunt.hcl
│ ├── null-resource
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── dev
│ │ │ ├── main.tf
│ │ │ └── terragrunt.hcl
│ │ ├── prod
│ │ │ ├── main.tf
│ │ │ └── terragrunt.hcl
│ │ └── terragrunt.hcl
│ └── source-resource
│ │ ├── README.md
│ │ ├── module
│ │ └── null-module
│ │ │ └── main.tf
│ │ ├── simple
│ │ └── terragrunt.hcl
│ │ ├── terragrunt.hcl
│ │ └── with-env-yaml
│ │ ├── env0.yml
│ │ └── terragrunt.hcl
├── run-all
│ └── dependencies
│ │ ├── .gitignore
│ │ ├── backend-app
│ │ ├── main.tf
│ │ └── terragrunt.hcl
│ │ └── vpc
│ │ ├── main.tf
│ │ └── terragrunt.hcl
└── terragrunt.hcl
└── vsphere
└── vm-http-server
├── README.md
├── data.tf
├── env0.yml
├── http_server.py
├── main.tf
├── outputs.tf
└── variables.tf
/.gitignore:
--------------------------------------------------------------------------------
1 | ### IDE
2 | # Jetbrains
3 | .idea/
4 |
5 | ### macOS template
6 | # General
7 | .DS_Store
8 | .AppleDouble
9 | .LSOverride
10 |
11 | # Thumbnails
12 | ._*
13 |
14 | .terraform
15 | *.tfstate
16 | *.tfstate.backup
17 |
18 | node_modules/
19 |
20 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "misc/git-submodules/https/child"]
2 | path = misc/git-submodules/https/child
3 | url = https://github.com/env0/templates-git-submodule
4 | [submodule "misc/git-submodules/relative/child"]
5 | path = misc/git-submodules/relative/child
6 | url = ../templates-git-submodule
7 |
--------------------------------------------------------------------------------
/aws/custom-remote-state-bucket/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.0"
3 | }
4 |
5 | module "remote_state_bucket" {
6 | source = "github.com/env0/remote-state-bucket-module/aws"
7 |
8 | # Module-specific inputs
9 | external_id = "64922d09-2a1f-4f5b-b978-4f5e18f5e3b6"
10 | state_bucket_name = "custom-rbe-bucket-integration-tests-states-bucket"
11 | region = "us-west-2"
12 | env0_aws_role_name = "arn:aws:iam::170412844252:role/remote-backend-bors"
13 | }
14 |
15 | output "bucket_name" {
16 | value = module.remote_state_bucket.bucket_name
17 | }
18 |
19 | output "role_arn" {
20 | value = module.remote_state_bucket.role_arn
21 | }
22 |
23 | output "external_id" {
24 | value = module.remote_state_bucket.external_id
25 | }
26 |
27 | output "region" {
28 | value = module.remote_state_bucket.region
29 | }
30 |
--------------------------------------------------------------------------------
/aws/ec2-redash/README.md:
--------------------------------------------------------------------------------
1 | # Redash instance on AWS EC2
2 | A Terraform 12 example of how to deploy an application onto an EC2 on AWS.
3 | In this example, we will deploy [Redash](https://redash.io/)
4 |
5 | 
6 |
7 | ## Configuration
8 | - `AWS_ACCESS_KEY_ID` - Your AWS Secret Key ID
9 | - `AWS_SECRET_ACCESS_KEY` - You AWS Secret key. **Tick the "Secret" checkbox on env0 when setting this one**
10 |
11 | ### Environment Variables
12 | None
13 |
14 | ### Terraform Variables
15 | - `instance_type` - The [ec2 instance type](https://aws.amazon.com/ec2/instance-types/) (Defaults to `t2.small`)
16 |
17 | ### Output
18 | - `tls_private_key`: The private key to be used in order to ssh to the ec2 instance
19 | - `instance_public_ip`: The public IP of your Redash instance - Click on the URL on the Outputs tab of env0 to check it out!
20 |
--------------------------------------------------------------------------------
/aws/ec2-redash/ec2.tf:
--------------------------------------------------------------------------------
1 | resource "aws_instance" "redash-instance" {
2 | ami = "ami-0c654c3ab463d22f6"
3 | instance_type = var.instance_type
4 | subnet_id = aws_subnet.redash-subnet.*.id[0]
5 | vpc_security_group_ids = [aws_security_group.redash-sg.id]
6 | key_name = aws_key_pair.redash-key-pair.key_name
7 | }
8 |
--------------------------------------------------------------------------------
/aws/ec2-redash/elastic-ip.tf:
--------------------------------------------------------------------------------
1 | resource "aws_eip" "redash-elastic-ip" {
2 | instance = aws_instance.redash-instance.id
3 | vpc = true
4 | }
5 |
--------------------------------------------------------------------------------
/aws/ec2-redash/key_pair.tf:
--------------------------------------------------------------------------------
1 | resource "tls_private_key" "private_key" {
2 | algorithm = "RSA"
3 | rsa_bits = 4096
4 | }
5 |
6 | resource "aws_key_pair" "redash-key-pair" {
7 | key_name = "redash-key-${random_uuid.uuid.result}"
8 | public_key = tls_private_key.private_key.public_key_openssh
9 | }
10 |
--------------------------------------------------------------------------------
/aws/ec2-redash/outputs.tf:
--------------------------------------------------------------------------------
1 | output "tls_private_key" {
2 | value = tls_private_key.private_key.private_key_pem
3 | description = "The private key to be used in order to ssh to the ec2 instance"
4 | sensitive = true
5 | }
6 |
7 | output "instance_public_ip" {
8 | value = aws_eip.redash-elastic-ip.public_ip
9 | description = "The public IP of your Redash instance"
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/aws/ec2-redash/providers.tf:
--------------------------------------------------------------------------------
1 | provider "aws" {
2 | region = var.aws_default_region
3 | }
4 |
5 | # Using these data sources allows the configuration to be
6 | # generic for any region.
7 | data "aws_region" "current" {}
8 |
9 | data "aws_availability_zones" "available" {}
10 |
--------------------------------------------------------------------------------
/aws/ec2-redash/random.tf:
--------------------------------------------------------------------------------
1 | resource "random_uuid" "uuid" { }
2 |
--------------------------------------------------------------------------------
/aws/ec2-redash/sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/env0/templates/80e65be109ec494bd2b4d5feefc20eb586d0b581/aws/ec2-redash/sample.png
--------------------------------------------------------------------------------
/aws/ec2-redash/security_group.tf:
--------------------------------------------------------------------------------
1 | resource "aws_security_group" "redash-sg" {
2 | name = "redash-sg"
3 | description = "Redash Seciurity group"
4 | vpc_id = aws_vpc.redash-vpc.id
5 |
6 | egress {
7 | from_port = 0
8 | to_port = 0
9 | protocol = "-1"
10 | cidr_blocks = ["0.0.0.0/0"]
11 | }
12 |
13 | tags = {
14 | "Name" = "redash-sg"
15 | "CreatedBy" = "env0"
16 | }
17 | }
18 |
19 | resource "aws_security_group_rule" "redash-group-rule-for-https" {
20 | description = "Allow HTTPS connection to the redash instance"
21 | from_port = 443
22 | protocol = "tcp"
23 | security_group_id = aws_security_group.redash-sg.id
24 | to_port = 443
25 | type = "ingress"
26 | cidr_blocks = ["0.0.0.0/0"]
27 | }
28 |
29 | resource "aws_security_group_rule" "redash-group-rule-for-http" {
30 | description = "Allow HTTP connection to the redash instance"
31 | from_port = 80
32 | protocol = "tcp"
33 | security_group_id = aws_security_group.redash-sg.id
34 | to_port = 80
35 | type = "ingress"
36 | cidr_blocks = ["0.0.0.0/0"]
37 | }
38 |
39 | resource "aws_security_group_rule" "redash-group-rule-for-ssh" {
40 | description = "Allow SSH connection to the redash instance"
41 | from_port = 22
42 | protocol = "tcp"
43 | security_group_id = aws_security_group.redash-sg.id
44 | to_port = 22
45 | type = "ingress"
46 | cidr_blocks = ["0.0.0.0/0"]
47 | }
48 |
--------------------------------------------------------------------------------
/aws/ec2-redash/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_default_region" { default = "us-east-1"}
2 | variable "instance_type" { default = "t2.small"}
3 |
--------------------------------------------------------------------------------
/aws/ec2-redash/vpc.tf:
--------------------------------------------------------------------------------
1 | #
2 | # VPC Resources
3 | # * VPC
4 | # * Subnets
5 | # * Internet Gateway
6 | # * Route Table
7 | #
8 |
9 | resource "aws_vpc" "redash-vpc" {
10 | cidr_block = "10.0.0.0/16"
11 | enable_dns_hostnames = true
12 | enable_dns_support = true
13 | }
14 |
15 | resource "aws_subnet" "redash-subnet" {
16 | count = 1
17 | availability_zone = data.aws_availability_zones.available.names[count.index]
18 | cidr_block = "10.0.${count.index}.0/24"
19 | vpc_id = aws_vpc.redash-vpc.id
20 | }
21 |
22 | resource "aws_internet_gateway" "redash-ig" {
23 | vpc_id = aws_vpc.redash-vpc.id
24 | }
25 |
26 | resource "aws_route_table" "redash-rt" {
27 | vpc_id = aws_vpc.redash-vpc.id
28 |
29 | route {
30 | cidr_block = "0.0.0.0/0"
31 | gateway_id = aws_internet_gateway.redash-ig.id
32 | }
33 | }
34 |
35 | resource "aws_route_table_association" "redash-rt-association" {
36 | count = 1
37 | subnet_id = aws_subnet.redash-subnet.*.id[count.index]
38 | route_table_id = aws_route_table.redash-rt.id
39 | }
40 |
--------------------------------------------------------------------------------
/aws/ec2-simple/main.tf:
--------------------------------------------------------------------------------
1 | provider "aws" {
2 | region = "us-east-1"
3 | }
4 |
5 | data "aws_ami" "ubuntu" {
6 | most_recent = true
7 |
8 | filter {
9 | name = "name"
10 | values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
11 | }
12 |
13 | filter {
14 | name = "virtualization-type"
15 | values = ["hvm"]
16 | }
17 |
18 | owners = ["099720109477"] # Canonical
19 | }
20 |
21 | resource "aws_instance" "web" {
22 | ami = data.aws_ami.ubuntu.id
23 | instance_type = "t3.micro"
24 |
25 | tags = {
26 | Name = "EC2-Micro"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/aws/github-ee/dns.tf:
--------------------------------------------------------------------------------
1 | resource "aws_route53_record" "github-ee-record" {
2 | name = var.dns_name
3 | type = "A"
4 | zone_id = var.aws_route53_zone_id
5 | ttl = "300"
6 | records = [aws_instance.github_ee.public_ip]
7 | }
8 |
--------------------------------------------------------------------------------
/aws/github-ee/main.tf:
--------------------------------------------------------------------------------
1 | resource "aws_subnet" "github_ee" {
2 | vpc_id = var.vpc_id
3 | cidr_block = var.cidr_block
4 | map_public_ip_on_launch = true
5 | availability_zone = var.availability_zone
6 |
7 | tags = {
8 | Name = "GithubEE-${var.gh_ee_version}"
9 | }
10 | }
11 |
12 | resource "aws_instance" "github_ee" {
13 | ami = var.github_ami
14 | key_name = aws_key_pair.github_ee_key.key_name
15 | instance_type = var.instance_type
16 | vpc_security_group_ids = [aws_security_group.github_ee_security_group.id]
17 | subnet_id = aws_subnet.github_ee.id
18 | associate_public_ip_address = true
19 | availability_zone = var.availability_zone
20 |
21 | ebs_block_device {
22 | device_name = "/dev/xvdf"
23 | volume_size = 150
24 | }
25 |
26 | root_block_device {
27 | volume_size = 200
28 | }
29 |
30 | tags = {
31 | Name = "GithubEE-${var.gh_ee_version}"
32 | }
33 | }
34 |
35 |
36 |
37 | resource "aws_key_pair" "github_ee_key" {
38 | key_name = "github-ee-${var.gh_ee_version}-ssh"
39 | public_key = tls_private_key.github_ee.public_key_openssh
40 | }
41 |
42 | resource "tls_private_key" "github_ee" {
43 | algorithm = "RSA"
44 | rsa_bits = 4096
45 | }
46 |
--------------------------------------------------------------------------------
/aws/github-ee/security-group.tf:
--------------------------------------------------------------------------------
1 | data "aws_ip_ranges" "ec2_instance_connect_ips" {
2 | services = ["ec2_instance_connect"]
3 | }
4 |
5 | resource "aws_security_group" "github_ee_security_group" {
6 | name = "github-ee-${var.gh_ee_version}-sg"
7 | vpc_id = var.vpc_id
8 |
9 | ingress {
10 | description = "Git over SSH access. Clone, fetch, and push operations to public/private repositories supported."
11 | protocol = "tcp"
12 | from_port = 22
13 | to_port = 22
14 | cidr_blocks = ["0.0.0.0/0"]
15 | }
16 |
17 | ingress {
18 | description = "Simple Git protocol port. Clone and fetch operations to public repositories only"
19 | protocol = "tcp"
20 | from_port = 9418
21 | to_port = 9418
22 | cidr_blocks = ["0.0.0.0/0"]
23 | }
24 |
25 | ingress {
26 | description = "Web application and Git over HTTP access."
27 | protocol = "tcp"
28 | from_port = 80
29 | to_port = 80
30 | cidr_blocks = ["0.0.0.0/0"]
31 | }
32 |
33 | ingress {
34 | description = "Web application and Git over HTTPS access."
35 | protocol = "tcp"
36 | from_port = 443
37 | to_port = 443
38 | cidr_blocks = ["0.0.0.0/0"]
39 | }
40 |
41 | ingress {
42 | description = "Plain-text web based Management Console. Not required unless SSL is disabled manually."
43 | protocol = "tcp"
44 | from_port = 8080
45 | to_port = 8080
46 | cidr_blocks = ["0.0.0.0/0"]
47 | }
48 |
49 | ingress {
50 | description = "Secure web based Management Console. Required for basic installation and configuration."
51 | protocol = "tcp"
52 | from_port = 8443
53 | to_port = 8443
54 | cidr_blocks = ["0.0.0.0/0"]
55 | }
56 |
57 | // This is for enabling ec2_instance_connect for this instance
58 | // We are taking the IPs from AWS to allow them to access SSH on port 22
59 | ingress {
60 | protocol = "tcp"
61 | from_port = 122
62 | to_port = 122
63 | cidr_blocks = data.aws_ip_ranges.ec2_instance_connect_ips.cidr_blocks
64 | }
65 |
66 | ingress {
67 | protocol = "tcp"
68 | from_port = 122
69 | to_port = 122
70 | cidr_blocks = ["0.0.0.0/0"]
71 | }
72 |
73 | egress {
74 | protocol = -1
75 | from_port = 0
76 | to_port = 0
77 | cidr_blocks = ["0.0.0.0/0"]
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/aws/github-ee/variables.tf:
--------------------------------------------------------------------------------
1 | variable "aws_default_region" {
2 | default = "us-east-1"
3 | }
4 |
5 | variable "github_ami" {
6 | description = "The AMI of the github instance"
7 | }
8 |
9 | variable "instance_type" {
10 | description = "EC2 machine type"
11 | default = "r3.large"
12 | }
13 |
14 | variable "vpc_id" {
15 | description = "The vpc id for this instance"
16 | }
17 |
18 | variable "aws_route53_zone_id" {
19 | description = "Zone id for route 53 defaults to dev's"
20 | }
21 |
22 | variable "dns_name" {
23 | description = "dns for github ee"
24 | }
25 |
26 | variable "cidr_block" {
27 | description = "VPC subnet for github ee"
28 | }
29 |
30 | variable "availability_zone" {
31 | description = "Availability zone for ec2"
32 | default = "us-east-1a"
33 | }
34 |
35 | variable "gh_ee_version" {
36 | description = "prefix"
37 | }
38 |
--------------------------------------------------------------------------------
/aws/hello-world/README.md:
--------------------------------------------------------------------------------
1 | # Hello World on AWS
2 | A static website S3 bucket serving an HTML greeting the user with his own custom cat imag
3 | 
4 |
5 | ## Configuration
6 |
7 | ### Environment Variables
8 | - `USER` - sets the user name to greet on the html generated from `index.template.html`
9 |
10 | ### Terraform Variables
11 | None
12 |
--------------------------------------------------------------------------------
/aws/hello-world/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | terraformInit:
6 | before:
7 | - echo Replacing !!!USER!!! with $USER in index.html
8 | - sed 's/!!!USER!!!/'"$USER"'/g' index.template.html > index.html
9 |
--------------------------------------------------------------------------------
/aws/hello-world/index.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello from env0!
6 |
7 |
8 |
37 |
38 |
39 |
40 |
41 |
Welcome to your own environment !!!USER!!!
42 |
43 |

44 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/aws/hello-world/main.tf:
--------------------------------------------------------------------------------
1 | provider "aws" {
2 | version = "~> 4.0"
3 | region = "us-east-1"
4 | }
5 |
6 | terraform {
7 | required_version = ">= 0.13"
8 | }
9 |
--------------------------------------------------------------------------------
/aws/hello-world/output.tf:
--------------------------------------------------------------------------------
1 | output "url" {
2 | value = aws_s3_bucket_website_configuration.website_config.website_endpoint
3 | }
4 |
--------------------------------------------------------------------------------
/aws/hello-world/s3.tf:
--------------------------------------------------------------------------------
1 | provider "random" {}
2 |
3 | resource "random_string" "random" {
4 | length = 16
5 | special = false
6 | min_lower = 16
7 | }
8 |
9 | resource "aws_s3_bucket" "website_bucket" {
10 | bucket = "hello-env0-${random_string.random.result}"
11 | force_destroy = true
12 | }
13 |
14 | resource "aws_s3_bucket_website_configuration" "website_config" {
15 | bucket = aws_s3_bucket.website_bucket.id
16 |
17 | index_document {
18 | suffix = "index.html"
19 | }
20 |
21 | error_document {
22 | key = "index.html"
23 | }
24 | }
25 |
26 | resource "aws_s3_bucket_ownership_controls" "bucket_ownership" {
27 | bucket = aws_s3_bucket.website_bucket.id
28 | rule {
29 | object_ownership = "BucketOwnerPreferred"
30 | }
31 | }
32 |
33 | resource "aws_s3_bucket_public_access_block" "bucket_public_access_block" {
34 | bucket = aws_s3_bucket.website_bucket.id
35 |
36 | block_public_acls = false
37 | block_public_policy = false
38 | ignore_public_acls = false
39 | restrict_public_buckets = false
40 | }
41 |
42 | # Adding delay because PutBucketPolicy API below can fail due to race condition with the removal of public access block
43 | # This is a recommendation by AWS support :(
44 | resource "null_resource" "delay" {
45 | depends_on = [
46 | aws_s3_bucket_ownership_controls.bucket_ownership,
47 | aws_s3_bucket_public_access_block.bucket_public_access_block
48 | ]
49 |
50 | provisioner "local-exec" {
51 | command = "sleep 5"
52 | }
53 | }
54 |
55 | resource "aws_s3_bucket_policy" "website_bucket_policy" {
56 | bucket = aws_s3_bucket.website_bucket.id
57 | depends_on = [
58 | null_resource.delay
59 | ]
60 |
61 | policy = jsonencode({
62 | Version = "2012-10-17"
63 | Statement = [
64 | {
65 | Sid = "Allow-Public-Access-To-Bucket"
66 | Effect = "Allow"
67 | Principal = "*"
68 | Action = "s3:GetObject"
69 | Resource = [
70 | "arn:aws:s3:::${aws_s3_bucket.website_bucket.bucket}/*"
71 | ]
72 | },
73 | ]
74 | })
75 | }
76 |
77 | resource "aws_s3_object" "object" {
78 | bucket = aws_s3_bucket.website_bucket.bucket
79 | key = "index.html"
80 | source = "index.html"
81 | content_type = "text/html"
82 | }
83 |
--------------------------------------------------------------------------------
/aws/hello-world/sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/env0/templates/80e65be109ec494bd2b4d5feefc20eb586d0b581/aws/hello-world/sample.png
--------------------------------------------------------------------------------
/aws/iam/env0-cost-estimation-role/README.md:
--------------------------------------------------------------------------------
1 | # env0 Cost Estimation IAM Role Template
2 |
3 | This template creates the IAM role and policy as described in the [How to Setup AWS Costs with env0](https://docs.env0.com/docs/aws-costs) documentation.
4 | The outputs include the role ARN and External Id for use in configuring the credential in env0.
5 |
6 | ## Setup
7 |
8 | Once you've completed the [Getting Started with env0](https://docs.env0.com/docs/getting-started) onboarding process, having connected your VCS and AWS, you can either set this up as a [template](https://docs.env0.com/docs/create-your-first-template) (recommended) to simplify launching new projects (Eg. Dev, Stag, Prod) in the future, or launch it in a [new environment](https://docs.env0.com/docs/setting-up-a-new-environment) (Stack).
9 | (Please env0, correct your terminology to align with the tech industry... Docs are so hard.)
10 |
11 | Once the stack has completed, view the outputs to access the IAM Role ARN and External Id when [adding a new Cost Credential](https://docs.env0.com/docs/aws-costs#add-credentials-to-your-organization) in env0.
12 |
13 |
--------------------------------------------------------------------------------
/aws/iam/env0-cost-estimation-role/data.tf:
--------------------------------------------------------------------------------
1 | data "aws_caller_identity" "current" {}
2 |
--------------------------------------------------------------------------------
/aws/iam/env0-cost-estimation-role/env0-cost.tf:
--------------------------------------------------------------------------------
1 | resource "random_string" "external_id" {
2 | length = 32
3 | upper = true
4 | min_upper = 1
5 | lower = true
6 | min_lower = 1
7 | numeric = true
8 | min_numeric = 1
9 | special = false
10 | }
11 |
12 |
13 | resource "aws_iam_policy" "env0_cost" {
14 | name = "env0_cost"
15 | path = "/"
16 | description = "env0_cost"
17 |
18 | policy = < tf-plan.json
12 | - ./opa eval --fail-defined "data.terraform.validation.violations[msg]" --input tf-plan.json --data ./tf-lib.rego --data ./validation.rego --format values 1>&2
13 |
14 |
--------------------------------------------------------------------------------
/aws/opa-example/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.12"
3 | }
4 |
5 | provider "aws" {
6 | version = "~> 2.8"
7 | region = "us-east-1"
8 | }
9 |
10 | variable "ssh_cidr_block" {
11 | default = "0.0.0.0/0"
12 | }
13 |
14 | resource "aws_security_group" "allow_ssh" {
15 | name = "my_security_group"
16 | description = "Allow SSH Trafic"
17 |
18 | ingress {
19 | description = "Incoming ssh"
20 | from_port = 22
21 | to_port = 22
22 | protocol = "tcp"
23 | cidr_blocks = [var.ssh_cidr_block]
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/aws/opa-example/tf-lib.rego:
--------------------------------------------------------------------------------
1 | package terraform.library
2 |
3 | # Rego utils to work with Terraform
4 | # Copied from https://www.openpolicyagent.org/docs/latest/terraform/#working-with-modules
5 |
6 | resources := { r |
7 | some path, value
8 |
9 | # Walk over the JSON tree and check if the node we are
10 | # currently on is a module (either root or child) resources
11 | # value.
12 | walk(input.planned_values, [path, value])
13 |
14 | # Look for resources in the current value based on path
15 | rs := module_resources(path, value)
16 |
17 | # Aggregate them into `resources`
18 | r := rs[_]
19 | }
20 |
21 | # Variant to match root_module resources
22 | module_resources(path, value) = rs {
23 |
24 | # Expect something like:
25 | #
26 | # {
27 | # "root_module": {
28 | # "resources": [...],
29 | # ...
30 | # }
31 | # ...
32 | # }
33 | #
34 | # Where the path is [..., "root_module", "resources"]
35 |
36 | reverse_index(path, 1) == "resources"
37 | reverse_index(path, 2) == "root_module"
38 | rs := value
39 | }
40 |
41 | # Variant to match child_modules resources
42 | module_resources(path, value) = rs {
43 |
44 | # Expect something like:
45 | #
46 | # {
47 | # ...
48 | # "child_modules": [
49 | # {
50 | # "resources": [...],
51 | # ...
52 | # },
53 | # ...
54 | # ]
55 | # ...
56 | # }
57 | #
58 | # Where the path is [..., "child_modules", 0, "resources"]
59 | # Note that there will always be an index int between `child_modules`
60 | # and `resources`. We know that walk will only visit each one once,
61 | # so we shouldn't need to keep track of what the index is.
62 |
63 | reverse_index(path, 1) == "resources"
64 | reverse_index(path, 3) == "child_modules"
65 | rs := value
66 | }
67 |
68 | reverse_index(path, idx) = value {
69 | value := path[count(path) - idx]
70 | }
71 |
72 | list_contains_value(list, item) {
73 | list_item = list[_]
74 | list_item == item
75 | }
76 |
--------------------------------------------------------------------------------
/aws/opa-example/validation.rego:
--------------------------------------------------------------------------------
1 | package terraform.validation
2 |
3 | import data.terraform.library as lib
4 |
5 | default allow = false
6 |
7 | violations[msg] {
8 | no_open_cidr_blocks[msg]
9 | }
10 |
11 | no_open_cidr_blocks[msg] {
12 | open_cidr := "0.0.0.0/0"
13 | cidr_blocks := lib.resources[r].values.ingress[x].cidr_blocks
14 | lib.list_contains_value(cidr_blocks, open_cidr)
15 | msg = sprintf("No security groups should be open to all IP addresses. Resource in violation: %v",[r.address])
16 | }
17 |
18 | allow {
19 | count(violations) == 0
20 | }
21 |
--------------------------------------------------------------------------------
/aws/profile/README.md:
--------------------------------------------------------------------------------
1 | # Description
2 |
3 | This template demonstrates how to use custom profiles for a remote backend, and have the terraform plan and apply run with different credentials.
4 | [Profile is ignored when using AWS_ACCESS_KEY_ID](https://github.com/hashicorp/terraform-provider-aws/issues/10698). Also, using `AWS_PROFILE` is impossible before actually defining the profile.
5 | Therefore, the nicest way to accomplish this would be to dynamically define two profiles:
6 | 1. custom-profile - the profile that will run the backend
7 | 2. default - the profile that will run the plans and applies
8 |
9 | # Prerequisites
10 |
11 | 1. Make sure the backend bucket already exists in the custom profile's account
12 | 2. Replace `PROFILE_AWS_REGION`, `PROFILE_AWS_KEY`, `PROFILE_AWS_SECRET` with the credentials for the custom profile.
13 | 3. Replace `DEFAULT_AWS_REGION`, `DEFAULT_AWS_KEY`, `DEFAULT_AWS_SECRET` with the credentials that should run the plan and apply.
--------------------------------------------------------------------------------
/aws/profile/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | setupVariables:
6 | after:
7 | # The custom-profile will be used for the remote backend
8 | - aws configure set region $PROFILE_AWS_REGION --profile custom-profile
9 | - aws configure set aws_access_key_id $PROFILE_AWS_KEY --profile custom-profile
10 | - aws configure set aws_secret_access_key $PROFILE_AWS_SECRET --profile custom-profile
11 | # We create a default profile so that it could be used for the terraform plan/apply
12 | - aws configure set region $DEFAULT_AWS_REGION --profile default
13 | - aws configure set aws_access_key_id $DEFAULT_AWS_KEY --profile default
14 | - aws configure set aws_secret_access_key $DEFAULT_AWS_SECRET --profile default
15 |
--------------------------------------------------------------------------------
/aws/profile/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | backend "s3" {
3 | bucket = "bucket-in-custom-profile"
4 | key = "profile-state"
5 | region = "us-east-1"
6 | profile = "custom-profile"
7 | }
8 | }
9 |
10 | resource "aws_s3_bucket" "bucket" {
11 | bucket = "bucket-in-default-profile"
12 | acl = "private"
13 | }
14 |
--------------------------------------------------------------------------------
/aws/s3-bucket/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello from env0!
6 |
7 |
8 |
37 |
38 |
39 |
40 |
41 |
Welcome to your own environment
42 |
43 |

44 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/aws/s3-bucket/s3/output.tf:
--------------------------------------------------------------------------------
1 | output "url" {
2 | value = "${aws_s3_bucket.website_bucket.bucket_domain_name}"
3 | }
4 |
--------------------------------------------------------------------------------
/aws/s3-bucket/s3/s3.tf:
--------------------------------------------------------------------------------
1 | provider "aws" {
2 | version = "~> 4.0"
3 | region = "us-east-1"
4 | }
5 |
6 | provider "random" {}
7 |
8 | resource "random_string" "random" {
9 | length = "16"
10 | special = "false"
11 | min_lower = "16"
12 | }
13 |
14 | resource "aws_s3_bucket" "website_bucket" {
15 | bucket = "env0-s3-${random_string.random.result}"
16 | force_destroy = true
17 | }
18 |
19 | resource "aws_s3_bucket_ownership_controls" "bucket_ownership" {
20 | bucket = aws_s3_bucket.website_bucket.id
21 | rule {
22 | object_ownership = "BucketOwnerPreferred"
23 | }
24 | }
25 |
26 | resource "aws_s3_bucket_public_access_block" "bucket_public_access_block" {
27 | bucket = aws_s3_bucket.website_bucket.id
28 |
29 | block_public_acls = false
30 | block_public_policy = false
31 | ignore_public_acls = false
32 | restrict_public_buckets = false
33 | }
34 |
35 | # Delay before PutBucketPolicy due to API race condition
36 | resource "null_resource" "delay" {
37 | depends_on = [
38 | aws_s3_bucket_ownership_controls.bucket_ownership,
39 | aws_s3_bucket_public_access_block.bucket_public_access_block
40 | ]
41 |
42 | provisioner "local-exec" {
43 | command = "sleep 5"
44 | }
45 | }
46 |
47 | resource "aws_s3_bucket_policy" "bucket_policy" {
48 | bucket = aws_s3_bucket.website_bucket.id
49 | depends_on = [null_resource.delay]
50 |
51 | policy = <&2 && exit 1; fi
8 | onSuccess:
9 | - echo Replacing !!!USER!!! with $USER in index.html
10 | - sed 's/!!!USER!!!/'"$USER"'/g' index.template.html > index.html
11 | - awsv2 s3 cp index.html s3://$(aws cloudformation describe-stacks --output text --query "Stacks[].Outputs[?OutputKey=='BucketName'].OutputValue" --stack-name ${ENV0_WORKSPACE_NAME})/
12 | - 'echo "Site is available at: $(aws cloudformation describe-stacks --output text --query "Stacks[].Outputs[?OutputKey==''BucketUrl''].OutputValue" --stack-name ${ENV0_WORKSPACE_NAME})"'
13 |
14 | destroy:
15 | steps:
16 | setupVariables:
17 | after:
18 | - if [ -z "$AWS_DEFAULT_REGION" ]; then echo "AWS_DEFAULT_REGION must be provided" 1>&2 && exit 1; fi
19 | - echo emptying out the bucket before deleting the stack
20 | - awsv2 s3 rm s3://$(aws cloudformation describe-stacks --output text --query "Stacks[].Outputs[?OutputKey=='BucketName'].OutputValue" --stack-name ${ENV0_WORKSPACE_NAME})/ --recursive
21 |
--------------------------------------------------------------------------------
/cloudformation/hello-world/index.template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello from env0!
6 |
7 |
8 |
37 |
38 |
39 |
40 |
41 |
Welcome to your own environment !!!USER!!!
42 |
43 |

44 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/cloudformation/hello-world/sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/env0/templates/80e65be109ec494bd2b4d5feefc20eb586d0b581/cloudformation/hello-world/sample.png
--------------------------------------------------------------------------------
/cloudformation/hello-world/stack.yaml:
--------------------------------------------------------------------------------
1 | AWSTemplateFormatVersion: '2010-09-09'
2 | Resources:
3 | WebsiteBucket:
4 | Type: 'AWS::S3::Bucket'
5 | Properties:
6 | BucketName: !Join ['', ['website-bucket-cf-', !Select [2, !Split ['/', !Ref AWS::StackId]]]]
7 | PublicAccessBlockConfiguration:
8 | BlockPublicAcls: false
9 | BlockPublicPolicy: false
10 | IgnorePublicAcls: false
11 | RestrictPublicBuckets: false
12 | OwnershipControls:
13 | Rules:
14 | - ObjectOwnership: BucketOwnerPreferred
15 | WebsiteConfiguration:
16 | IndexDocument: index.html
17 | ErrorDocument: index.html
18 | WebsiteBucketPolicy:
19 | Type: 'AWS::S3::BucketPolicy'
20 | Properties:
21 | Bucket: !Ref WebsiteBucket
22 | PolicyDocument:
23 | Version: '2012-10-17'
24 | Statement:
25 | - Sid: Allow-Public-Access-To-Bucket
26 | Effect: Allow
27 | Principal:
28 | AWS: '*'
29 | Action:
30 | - s3:GetObject
31 | Resource:
32 | - !Join ['', ['arn:aws:s3:::', !Ref WebsiteBucket, '/*']]
33 | Outputs:
34 | BucketName:
35 | Value: !Ref WebsiteBucket
36 | Description: 'The name of the S3 bucket'
37 | BucketUrl:
38 | Value: !GetAtt WebsiteBucket.WebsiteURL
39 | Description: 'URL of the S3 bucket'
40 |
--------------------------------------------------------------------------------
/community-providers/pingdom/README.md:
--------------------------------------------------------------------------------
1 | ## Description
2 | This is a simple example on how to fetch `pingdom` terraform community provider using [env0 Custom Flows](https://docs.env0.com/docs/custom-flows) on **terraform v11 or v12**.
3 | > Note: For terraform v13 please refer to [terraform's official documentation](https://www.terraform.io/upgrade-guides/0-13.html#explicit-provider-source-locations) on how to specify community providers.
4 |
5 | ## Steps
6 | What we basically do in `env0.yml` file is:
7 | 1. Create the relevant `terraform.d` folder under the user's home folder (env0's runtime uses a dockerized `alpine` image, hence `os_arch` is `linux_amd64`).
8 | 2. Download the static artifact file of the `pingdom` community provider from github.
9 | 3. Allow execution permissions for the file so `terraform` can use it.
10 |
11 | > Note: Please pay attention that custom flow needs to be done before `terraform init` and in both `deploy` and `destroy` actions.
12 |
--------------------------------------------------------------------------------
/community-providers/pingdom/env0.yml:
--------------------------------------------------------------------------------
1 | deploy:
2 | steps:
3 | terraformInit:
4 | before:
5 | - mkdir -p $HOME/.terraform.d/plugins/linux_amd64
6 | - wget https://github.com/russellcardullo/terraform-provider-pingdom/releases/download/v1.1.1/terraform-provider-pingdom_v1.1.1_linux_amd64_static -O $HOME/.terraform.d/plugins/linux_amd64/terraform-provider-pingdom_v1.1.1
7 | - chmod +x $HOME/.terraform.d/plugins/linux_amd64/terraform-provider-pingdom_v1.1.1
8 | destroy:
9 | steps:
10 | terraformInit:
11 | before:
12 | - mkdir -p $HOME/.terraform.d/plugins/linux_amd64
13 | - wget https://github.com/russellcardullo/terraform-provider-pingdom/releases/download/v1.1.1/terraform-provider-pingdom_v1.1.1_linux_amd64_static -O $HOME/.terraform.d/plugins/linux_amd64/terraform-provider-pingdom_v1.1.1
14 | - chmod +x $HOME/.terraform.d/plugins/linux_amd64/terraform-provider-pingdom_v1.1.1
15 |
--------------------------------------------------------------------------------
/community-providers/pingdom/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.11.0"
3 | }
4 |
5 | provider "pingdom" {
6 | user = "user"
7 | password = "password"
8 | api_key = "dummy"
9 | }
10 |
11 | resource "pingdom_team" "rd" {
12 | name = "R&D"
13 | }
14 |
15 | resource "pingdom_user" "manager" {
16 | username = "Manager Cohen"
17 | }
18 |
19 | resource "pingdom_contact" "manager_contact" {
20 | user_id = pingdom_user.manager.id
21 | email = "john@doe.com"
22 | severity_level = "HIGH"
23 | }
24 |
--------------------------------------------------------------------------------
/custom-flows/external-script.yaml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | setupVariables:
6 | after:
7 | - git clone https://$ENV0_VCS_ACCESS_TOKEN@github.com/env0/templates.git external-repo
8 |
9 | terraformPlan:
10 | before:
11 | - ./external-repo/custom-flows/scripts/script.sh
12 |
--------------------------------------------------------------------------------
/custom-flows/opa-polices/null-resource.rego:
--------------------------------------------------------------------------------
1 | package resource.limit
2 |
3 | import input as tfplan
4 |
5 | default allow := false
6 |
7 | allow := true {
8 | score < 2
9 | }
10 |
11 | # Consider exactly these resource types in calculations
12 | resource_types := {"null_resource"}
13 |
14 | score := s {
15 | all := [ x |
16 | some resource_type
17 | new := num_creates[resource_type];
18 | mod := num_modifies[resource_type];
19 | x := new + mod
20 | ]
21 | s := sum(all)
22 | }
23 |
24 | ####################
25 | # Terraform Library
26 | ####################
27 |
28 | # list of all resources of a given type
29 | resources[resource_type] := all {
30 | some resource_type
31 | resource_types[resource_type]
32 | all := [name |
33 | name:= tfplan.resource_changes[_]
34 | name.type == resource_type
35 | ]
36 | }
37 |
38 | # number of creations of resources of a given type
39 | num_creates[resource_type] := num {
40 | some resource_type
41 | resource_types[resource_type]
42 | all := resources[resource_type]
43 | creates := [res | res:= all[_]; res.change.actions[_] == "create"]
44 | num := count(creates)
45 | }
46 |
47 | # number of modifications to resources of a given type
48 | num_modifies[resource_type] := num {
49 | some resource_type
50 | resource_types[resource_type]
51 | all := resources[resource_type]
52 | modifies := [res | res:= all[_]; res.change.actions[_] == "update"]
53 | num := count(modifies)
54 | }
55 |
--------------------------------------------------------------------------------
/custom-flows/opa.yaml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | setupVariables:
6 | after:
7 | - curl -L -o opa https://openpolicyagent.org/downloads/v0.46.1/opa_linux_amd64_static
8 | - chmod 755 ./opa
9 | - git clone https://$ENV0_VCS_ACCESS_TOKEN@github.com/env0/templates.git external-repo
10 |
11 | terraformPlan:
12 | after:
13 | - terraform show -json .tf-plan >> tfplan.json
14 | - ./opa eval --format pretty -i tfplan.json -d ./external-repo/custom-flows/opa-polices/null-resource.rego --fail "data.resource.limit.allow = true"
15 |
--------------------------------------------------------------------------------
/custom-flows/scripts/script.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | echo Hello! Hi I am a script from another world
4 | ls -al .
5 |
--------------------------------------------------------------------------------
/gcp/bq-dataset/README.md:
--------------------------------------------------------------------------------
1 | This TF needs two Environment variables
2 |
3 | - `GOOGLE_CREDENTIALS` - You need to download a JSON [service-account key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys#creating_service_account_keys), and copy paste that
4 | - `GOOGLE_PROJECT` - The name of the GCP project.
5 |
--------------------------------------------------------------------------------
/gcp/bq-dataset/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = "=0.14.11"
3 | }
4 |
5 | resource "random_id" "id" {
6 | byte_length = 8
7 | }
8 |
9 | resource "google_bigquery_dataset" "dataset" {
10 | dataset_id = "env0_test_${random_id.id.dec}"
11 | }
12 |
--------------------------------------------------------------------------------
/gcp/container-cluster/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | backend "gcs" {
3 | bucket = "env0-gcp-backend-state-bucket"
4 | prefix = "container_cluster_states"
5 | }
6 | }
7 |
8 | # Copied from https://www.terraform.io/docs/providers/google/r/container_node_pool.html
9 |
10 | resource "google_container_cluster" "primary" {
11 | name = "my-gke-cluster"
12 | location = "us-central1"
13 |
14 | # We can't create a cluster with no node pool defined, but we want to only use
15 | # separately managed node pools. So we create the smallest possible default
16 | # node pool and immediately delete it.
17 | remove_default_node_pool = true
18 | initial_node_count = 1
19 |
20 | resource_labels = {
21 | my_label_1 = "label-1"
22 | my_label_1a = "label-1a"
23 | }
24 | }
25 |
26 | resource "google_container_node_pool" "primary_preemptible_nodes" {
27 | name = "my-node-pool"
28 | location = "us-central1"
29 | cluster = google_container_cluster.primary.name
30 | node_count = 1
31 |
32 | node_config {
33 | preemptible = true
34 | machine_type = "n1-standard-1"
35 |
36 | oauth_scopes = [
37 | "https://www.googleapis.com/auth/logging.write",
38 | "https://www.googleapis.com/auth/monitoring",
39 | ]
40 |
41 | labels = {
42 | my_label_2 = "label-2"
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/gcp/service-account-key/README.md:
--------------------------------------------------------------------------------
1 | ## Description
2 | This terraform template creates a GCP [service account](https://cloud.google.com/iam/docs/service-accounts#what_are_service_accounts) under your project and configures & exports a JSON key for that account
3 |
4 | ## Required environment variables:
5 |
6 | - `GOOGLE_CREDENTIALS` - You need to download a JSON [service-account key](https://cloud.google.com/iam/docs/creating-managing-service-account-keys#creating_service_account_keys), and copy paste that
7 | - `GOOGLE_PROJECT` - The name of the GCP project.
8 |
9 | ## Relevant Outputs:
10 | - `public key` - The public key, base64 encoded
11 | - `private_key` - The private key in JSON format, base64 encoded.
12 |
13 |
14 | For additional info, please visit terraform's [official docs](https://www.terraform.io/docs/providers/google/r/google_service_account_key.html).
--------------------------------------------------------------------------------
/gcp/service-account-key/mainf.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">=0.12.3"
3 | }
4 |
5 | provider "google" {
6 | version = ">=3.0.0"
7 | project = var.project
8 | }
9 |
10 | resource "google_service_account" "account" {
11 | account_id = var.account_id
12 | display_name = var.account_display_name
13 | }
14 |
15 | resource "google_service_account_key" "key" {
16 | service_account_id = google_service_account.account.name
17 | public_key_type = "TYPE_X509_PEM_FILE"
18 | }
--------------------------------------------------------------------------------
/gcp/service-account-key/variables.tf:
--------------------------------------------------------------------------------
1 | variable "account_id" {
2 | type = string
3 | description = "The id of the service account that will be created"
4 | }
5 |
6 | variable "account_display_name" {
7 | type = string
8 | description = "The display name of the service account that will be created"
9 | }
10 |
11 | variable "project" {
12 | type = string
13 | description = "The GCP project id"
14 | }
--------------------------------------------------------------------------------
/helm/dummy/.helmignore:
--------------------------------------------------------------------------------
1 | # Patterns to ignore when building packages.
2 | # This supports shell glob matching, relative path matching, and
3 | # negation (prefixed with !). Only one pattern per line.
4 | .DS_Store
5 | # Common VCS dirs
6 | .git/
7 | .gitignore
8 | .bzr/
9 | .bzrignore
10 | .hg/
11 | .hgignore
12 | .svn/
13 | # Common backup files
14 | *.swp
15 | *.bak
16 | *.tmp
17 | *.orig
18 | *~
19 | # Various IDEs
20 | .project
21 | .idea/
22 | *.tmproj
23 | .vscode/
24 |
--------------------------------------------------------------------------------
/helm/dummy/Chart.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v2
2 | name: dummy
3 | description: A Helm chart for Kubernetes
4 |
5 | # A chart can be either an 'application' or a 'library' chart.
6 | #
7 | # Application charts are a collection of templates that can be packaged into versioned archives
8 | # to be deployed.
9 | #
10 | # Library charts provide useful utilities or functions for the chart developer. They're included as
11 | # a dependency of application charts to inject those utilities and functions into the rendering
12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed.
13 | type: application
14 |
15 | # This is the chart version. This version number should be incremented each time you make changes
16 | # to the chart and its templates, including the app version.
17 | # Versions are expected to follow Semantic Versioning (https://semver.org/)
18 | version: 0.1.0
19 |
20 | # This is the version number of the application being deployed. This version number should be
21 | # incremented each time you make changes to the application. Versions are not expected to
22 | # follow Semantic Versioning. They should reflect the version the application is using.
23 | # It is recommended to use it with quotes.
24 | appVersion: "1.16.0"
25 |
--------------------------------------------------------------------------------
/helm/dummy/README.md:
--------------------------------------------------------------------------------
1 | # Helm Dummy Chart
2 |
3 | This dummy chart contains the k8s resources that requires for creating a working Nginx web server.
4 |
5 | ### Connect to your K8s cluster in env0
6 |
7 | In order to apply this chart as an env0 [Helm template](https://docs.env0.com/docs/helm), you'll have to first connect to your cluster in env0.
8 | It can be easily done by following our [Kubernetes integration guide](https://docs.env0.com/docs/connect-your-cloud-account#kubernetes).
--------------------------------------------------------------------------------
/helm/dummy/templates/NOTES.txt:
--------------------------------------------------------------------------------
1 | 1. Get the application URL by running these commands:
2 | {{- if .Values.ingress.enabled }}
3 | {{- range $host := .Values.ingress.hosts }}
4 | {{- range .paths }}
5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
6 | {{- end }}
7 | {{- end }}
8 | {{- else if contains "NodePort" .Values.service.type }}
9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "dummy.fullname" . }})
10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
11 | echo http://$NODE_IP:$NODE_PORT
12 | {{- else if contains "LoadBalancer" .Values.service.type }}
13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available.
14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "dummy.fullname" . }}'
15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "dummy.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
16 | echo http://$SERVICE_IP:{{ .Values.service.port }}
17 | {{- else if contains "ClusterIP" .Values.service.type }}
18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "dummy.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
19 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
20 | echo "Visit http://127.0.0.1:8080 to use your application"
21 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
22 | {{- end }}
23 |
--------------------------------------------------------------------------------
/helm/dummy/templates/_helpers.tpl:
--------------------------------------------------------------------------------
1 | {{/*
2 | Expand the name of the chart.
3 | */}}
4 | {{- define "dummy.name" -}}
5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
6 | {{- end }}
7 |
8 | {{/*
9 | Create a default fully qualified app name.
10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
11 | If release name contains chart name it will be used as a full name.
12 | */}}
13 | {{- define "dummy.fullname" -}}
14 | {{- if .Values.fullnameOverride }}
15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
16 | {{- else }}
17 | {{- $name := default .Chart.Name .Values.nameOverride }}
18 | {{- if contains $name .Release.Name }}
19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }}
20 | {{- else }}
21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
22 | {{- end }}
23 | {{- end }}
24 | {{- end }}
25 |
26 | {{/*
27 | Create chart name and version as used by the chart label.
28 | */}}
29 | {{- define "dummy.chart" -}}
30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
31 | {{- end }}
32 |
33 | {{/*
34 | Common labels
35 | */}}
36 | {{- define "dummy.labels" -}}
37 | helm.sh/chart: {{ include "dummy.chart" . }}
38 | {{ include "dummy.selectorLabels" . }}
39 | {{- if .Chart.AppVersion }}
40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
41 | {{- end }}
42 | app.kubernetes.io/managed-by: {{ .Release.Service }}
43 | {{- end }}
44 |
45 | {{/*
46 | Selector labels
47 | */}}
48 | {{- define "dummy.selectorLabels" -}}
49 | app.kubernetes.io/name: {{ include "dummy.name" . }}
50 | app.kubernetes.io/instance: {{ .Release.Name }}
51 | {{- end }}
52 |
53 | {{/*
54 | Create the name of the service account to use
55 | */}}
56 | {{- define "dummy.serviceAccountName" -}}
57 | {{- if .Values.serviceAccount.create }}
58 | {{- default (include "dummy.fullname" .) .Values.serviceAccount.name }}
59 | {{- else }}
60 | {{- default "default" .Values.serviceAccount.name }}
61 | {{- end }}
62 | {{- end }}
63 |
--------------------------------------------------------------------------------
/helm/dummy/templates/deployment.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: apps/v1
2 | kind: Deployment
3 | metadata:
4 | name: {{ include "dummy.fullname" . }}
5 | labels:
6 | {{- include "dummy.labels" . | nindent 4 }}
7 | spec:
8 | {{- if not .Values.autoscaling.enabled }}
9 | replicas: {{ .Values.replicaCount }}
10 | {{- end }}
11 | selector:
12 | matchLabels:
13 | {{- include "dummy.selectorLabels" . | nindent 6 }}
14 | template:
15 | metadata:
16 | {{- with .Values.podAnnotations }}
17 | annotations:
18 | {{- toYaml . | nindent 8 }}
19 | {{- end }}
20 | labels:
21 | {{- include "dummy.selectorLabels" . | nindent 8 }}
22 | spec:
23 | {{- with .Values.imagePullSecrets }}
24 | imagePullSecrets:
25 | {{- toYaml . | nindent 8 }}
26 | {{- end }}
27 | serviceAccountName: {{ include "dummy.serviceAccountName" . }}
28 | securityContext:
29 | {{- toYaml .Values.podSecurityContext | nindent 8 }}
30 | containers:
31 | - name: {{ .Chart.Name }}
32 | securityContext:
33 | {{- toYaml .Values.securityContext | nindent 12 }}
34 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
35 | imagePullPolicy: {{ .Values.image.pullPolicy }}
36 | ports:
37 | - name: http
38 | containerPort: 80
39 | protocol: TCP
40 | livenessProbe:
41 | httpGet:
42 | path: /
43 | port: http
44 | readinessProbe:
45 | httpGet:
46 | path: /
47 | port: http
48 | resources:
49 | {{- toYaml .Values.resources | nindent 12 }}
50 | {{- with .Values.nodeSelector }}
51 | nodeSelector:
52 | {{- toYaml . | nindent 8 }}
53 | {{- end }}
54 | {{- with .Values.affinity }}
55 | affinity:
56 | {{- toYaml . | nindent 8 }}
57 | {{- end }}
58 | {{- with .Values.tolerations }}
59 | tolerations:
60 | {{- toYaml . | nindent 8 }}
61 | {{- end }}
62 |
--------------------------------------------------------------------------------
/helm/dummy/templates/hpa.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.autoscaling.enabled }}
2 | apiVersion: autoscaling/v2beta1
3 | kind: HorizontalPodAutoscaler
4 | metadata:
5 | name: {{ include "dummy.fullname" . }}
6 | labels:
7 | {{- include "dummy.labels" . | nindent 4 }}
8 | spec:
9 | scaleTargetRef:
10 | apiVersion: apps/v1
11 | kind: Deployment
12 | name: {{ include "dummy.fullname" . }}
13 | minReplicas: {{ .Values.autoscaling.minReplicas }}
14 | maxReplicas: {{ .Values.autoscaling.maxReplicas }}
15 | metrics:
16 | {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
17 | - type: Resource
18 | resource:
19 | name: cpu
20 | targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
21 | {{- end }}
22 | {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
23 | - type: Resource
24 | resource:
25 | name: memory
26 | targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
27 | {{- end }}
28 | {{- end }}
29 |
--------------------------------------------------------------------------------
/helm/dummy/templates/ingress.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.ingress.enabled -}}
2 | {{- $fullName := include "dummy.fullname" . -}}
3 | {{- $svcPort := .Values.service.port -}}
4 | {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
5 | {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
6 | {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
7 | {{- end }}
8 | {{- end }}
9 | {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
10 | apiVersion: networking.k8s.io/v1
11 | {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
12 | apiVersion: networking.k8s.io/v1beta1
13 | {{- else -}}
14 | apiVersion: extensions/v1beta1
15 | {{- end }}
16 | kind: Ingress
17 | metadata:
18 | name: {{ $fullName }}
19 | labels:
20 | {{- include "dummy.labels" . | nindent 4 }}
21 | {{- with .Values.ingress.annotations }}
22 | annotations:
23 | {{- toYaml . | nindent 4 }}
24 | {{- end }}
25 | spec:
26 | {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
27 | ingressClassName: {{ .Values.ingress.className }}
28 | {{- end }}
29 | {{- if .Values.ingress.tls }}
30 | tls:
31 | {{- range .Values.ingress.tls }}
32 | - hosts:
33 | {{- range .hosts }}
34 | - {{ . | quote }}
35 | {{- end }}
36 | secretName: {{ .secretName }}
37 | {{- end }}
38 | {{- end }}
39 | rules:
40 | {{- range .Values.ingress.hosts }}
41 | - host: {{ .host | quote }}
42 | http:
43 | paths:
44 | {{- range .paths }}
45 | - path: {{ .path }}
46 | {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
47 | pathType: {{ .pathType }}
48 | {{- end }}
49 | backend:
50 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
51 | service:
52 | name: {{ $fullName }}
53 | port:
54 | number: {{ $svcPort }}
55 | {{- else }}
56 | serviceName: {{ $fullName }}
57 | servicePort: {{ $svcPort }}
58 | {{- end }}
59 | {{- end }}
60 | {{- end }}
61 | {{- end }}
62 |
--------------------------------------------------------------------------------
/helm/dummy/templates/service.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Service
3 | metadata:
4 | name: {{ include "dummy.fullname" . }}
5 | labels:
6 | {{- include "dummy.labels" . | nindent 4 }}
7 | spec:
8 | type: {{ .Values.service.type }}
9 | ports:
10 | - port: {{ .Values.service.port }}
11 | targetPort: http
12 | protocol: TCP
13 | name: http
14 | selector:
15 | {{- include "dummy.selectorLabels" . | nindent 4 }}
16 |
--------------------------------------------------------------------------------
/helm/dummy/templates/serviceaccount.yaml:
--------------------------------------------------------------------------------
1 | {{- if .Values.serviceAccount.create -}}
2 | apiVersion: v1
3 | kind: ServiceAccount
4 | metadata:
5 | name: {{ include "dummy.serviceAccountName" . }}
6 | labels:
7 | {{- include "dummy.labels" . | nindent 4 }}
8 | {{- with .Values.serviceAccount.annotations }}
9 | annotations:
10 | {{- toYaml . | nindent 4 }}
11 | {{- end }}
12 | {{- end }}
13 |
--------------------------------------------------------------------------------
/helm/dummy/templates/tests/test-connection.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Pod
3 | metadata:
4 | name: "{{ include "dummy.fullname" . }}-test-connection"
5 | labels:
6 | {{- include "dummy.labels" . | nindent 4 }}
7 | annotations:
8 | "helm.sh/hook": test
9 | spec:
10 | containers:
11 | - name: wget
12 | image: busybox
13 | command: ['wget']
14 | args: ['{{ include "dummy.fullname" . }}:{{ .Values.service.port }}']
15 | restartPolicy: Never
16 |
--------------------------------------------------------------------------------
/helm/dummy/values.yaml:
--------------------------------------------------------------------------------
1 | # Default values for dummy.
2 | # This is a YAML-formatted file.
3 | # Declare variables to be passed into your templates.
4 |
5 | replicaCount: 1
6 |
7 | image:
8 | repository: nginx
9 | pullPolicy: IfNotPresent
10 | # Overrides the image tag whose default is the chart appVersion.
11 | tag: ""
12 |
13 | imagePullSecrets: []
14 | nameOverride: "dummy"
15 | fullnameOverride: "dummy-chart"
16 |
17 | serviceAccount:
18 | # Specifies whether a service account should be created
19 | create: true
20 | # Annotations to add to the service account
21 | annotations: {}
22 | # The name of the service account to use.
23 | # If not set and create is true, a name is generated using the fullname template
24 | name: ""
25 |
26 | podAnnotations: {}
27 |
28 | podSecurityContext: {}
29 | # fsGroup: 2000
30 |
31 | securityContext: {}
32 | # capabilities:
33 | # drop:
34 | # - ALL
35 | # readOnlyRootFilesystem: true
36 | # runAsNonRoot: true
37 | # runAsUser: 1000
38 |
39 | service:
40 | type: ClusterIP
41 | port: 80
42 |
43 | ingress:
44 | enabled: false
45 | className: ""
46 | annotations: {}
47 | # kubernetes.io/ingress.class: nginx
48 | # kubernetes.io/tls-acme: "true"
49 | hosts:
50 | - host: chart-example.local
51 | paths:
52 | - path: /
53 | pathType: ImplementationSpecific
54 | tls: []
55 | # - secretName: chart-example-tls
56 | # hosts:
57 | # - chart-example.local
58 |
59 | resources: {}
60 | # We usually recommend not to specify default resources and to leave this as a conscious
61 | # choice for the user. This also increases chances charts run on environments with little
62 | # resources, such as Minikube. If you do want to specify resources, uncomment the following
63 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
64 | # limits:
65 | # cpu: 100m
66 | # memory: 128Mi
67 | # requests:
68 | # cpu: 100m
69 | # memory: 128Mi
70 |
71 | autoscaling:
72 | enabled: false
73 | minReplicas: 1
74 | maxReplicas: 100
75 | targetCPUUtilizationPercentage: 80
76 | # targetMemoryUtilizationPercentage: 80
77 |
78 | nodeSelector: {}
79 |
80 | tolerations: []
81 |
82 | affinity: {}
83 |
--------------------------------------------------------------------------------
/ibm/bare-metal/main.tf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/env0/templates/80e65be109ec494bd2b4d5feefc20eb586d0b581/ibm/bare-metal/main.tf
--------------------------------------------------------------------------------
/kubernetes/hello-world/README.md:
--------------------------------------------------------------------------------
1 | # Kubernetes Hello World
2 |
3 | Create a simple k8s namespace resource with a dynamic name using [env0 custom flow](https://docs.env0.com/docs/custom-flows).
4 |
5 | ### Connect to your K8s cluster in env0
6 | In order to apply this resource as an env0 [K8s template](https://docs.env0.com/docs/k8s), you'll have to first connect to your cluster in env0.
7 | It can be easily done by following our [Kubernetes integration guide](https://docs.env0.com/docs/connect-your-cloud-account#kubernetes).
8 |
9 | ### Getting the namespace name from env0
10 | The name of the created namespace will be taken from the env0 environment variable $ENV0_K8S_NAMESPACE. You can set it in the `Namespace` input when creating an environment.
--------------------------------------------------------------------------------
/kubernetes/hello-world/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | setupVariables:
6 | after: &set-namespace-name
7 | - echo "$(sed 's/!!!NAMESPACE!!!/'"$ENV0_K8S_NAMESPACE"'/g' namespace.yaml)" > namespace.yaml;
8 | - cat namespace.yaml
9 |
10 | destroy:
11 | steps:
12 | setupVariables:
13 | after: *set-namespace-name
14 |
--------------------------------------------------------------------------------
/kubernetes/hello-world/namespace.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: !!!NAMESPACE!!!
5 |
--------------------------------------------------------------------------------
/kubernetes/squid-proxy/README.md:
--------------------------------------------------------------------------------
1 | # Squid Proxy k8s installation
2 |
3 | This will setup a [squid proxy](http://www.squid-cache.org/) on a k8s server,
4 | used to 'simulate' hardened setups in which the env0 agent is behind a proxy server.
5 | All outgoing traffic from the agent must go through the proxy.
6 |
7 | ### Installing squid-proxy
8 |
9 | - Apply the `squid-proxy.yaml` file.
10 |
11 | ### Network Policy
12 |
13 | - The `network-policy.yaml` create a K8S network policy that will limit all traffic in a given namespace to go through the proxy.
14 | - Requires [calico](https://docs.aws.amazon.com/eks/latest/userguide/calico.html) to be installed - the vanilla k8s cluster doesn't enforce network policies.
15 | - Don't install without a specific namespace, it might affect core k8s services.
16 |
17 | ### Testing
18 |
19 | - `curl https://google.com` should not work
20 | - `curl https://google.com -x {proxy ip}:3128` should work
21 |
22 | ### Updating the agent
23 |
24 | - The agent should be installed with these values
25 |
26 | ```
27 | "httpProxy": "http://squid-proxy-service.squid-proxy.svc.cluster.local:80"
28 | "httpsProxy": "http://squid-proxy-service.squid-proxy.svc.cluster.local:80"
29 | "noProxy": "{K8S ApiService IP/DNS}"
30 | ```
31 |
--------------------------------------------------------------------------------
/kubernetes/squid-proxy/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | setupVariables:
6 | after: &login-k8s
7 | - aws eks --region=$AWS_DEFAULT_REGION update-kubeconfig --name $CLUSTER_NAME
8 |
9 | destroy:
10 | steps:
11 | setupVariables:
12 | after: *login-k8s
13 |
--------------------------------------------------------------------------------
/kubernetes/squid-proxy/network-policy.yaml:
--------------------------------------------------------------------------------
1 | # this will block all network egress except to the proxy
2 |
3 | apiVersion: networking.k8s.io/v1
4 | kind: NetworkPolicy
5 | metadata:
6 | name: default-deny-egress
7 | namespace: env0-agent-kushield # change this for the namespace you are working on - only requests to the proxy will be allowed
8 | spec:
9 | podSelector: {}
10 | policyTypes:
11 | - Egress
12 | egress:
13 | - to: # kube-dns
14 | - namespaceSelector:
15 | matchLabels:
16 | kubernetes.io/metadata.name: kube-system
17 | ports:
18 | - protocol: UDP
19 | port: 53
20 |
21 | - to: # proxy
22 | - podSelector:
23 | matchLabels:
24 | app: squid
25 | namespaceSelector:
26 | matchLabels:
27 | app: squid
28 | ports:
29 | - protocol: TCP
30 | port: 3128
31 |
--------------------------------------------------------------------------------
/kubernetes/squid-proxy/squid-proxy.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: squid-proxy
5 | labels:
6 | app: squid
7 |
8 | ---
9 | # Configuration for Squid-proxy
10 | # This config is VERY permissive - all traffic can go through the proxy transparently
11 | # Missing - user/pass authentication, SSL "bumping" (w/ self signed cert)
12 | kind: ConfigMap
13 | apiVersion: v1
14 | metadata:
15 | name: proxy-configmap
16 | namespace: squid-proxy
17 | data:
18 | squid.conf: |
19 | http_port 3128
20 |
21 | acl SSL_ports port 443
22 | acl CONNECT method CONNECT
23 |
24 | # allow all requests
25 | http_access allow all
26 | coredump_dir /var/spool/squid
27 |
28 | ---
29 | # Deployment for the proxy itself
30 | apiVersion: apps/v1
31 | kind: Deployment
32 | metadata:
33 | name: squid
34 | namespace: squid-proxy
35 | spec:
36 | replicas: 1
37 | selector:
38 | matchLabels:
39 | app: squid
40 | template:
41 | metadata:
42 | labels:
43 | app: squid
44 | spec:
45 | volumes:
46 | - name: proxy-config
47 | configMap:
48 | name: proxy-configmap
49 | containers:
50 | - name: squid
51 | image: ubuntu/squid:6.1-23.10_beta
52 | imagePullPolicy: IfNotPresent
53 | volumeMounts:
54 | - name: proxy-config
55 | mountPath: /etc/squid
56 | readOnly: true
57 | ports:
58 | - containerPort: 3128
59 | ---
60 | # Service for exposing the proxy
61 | apiVersion: v1
62 | kind: Service
63 | metadata:
64 | name: squid-proxy-service
65 | namespace: squid-proxy
66 | spec:
67 | selector:
68 | app: squid
69 | ports:
70 | - protocol: TCP
71 | port: 80
72 | targetPort: 3128
73 |
--------------------------------------------------------------------------------
/kubernetes/using-pulumi/Pulumi.yaml:
--------------------------------------------------------------------------------
1 | name: k8s-using-pulumi
2 | description: Create a K8s Pod
3 | runtime: nodejs
--------------------------------------------------------------------------------
/kubernetes/using-pulumi/README.md:
--------------------------------------------------------------------------------
1 | # Kubernetes Using Pulumi
2 |
3 | Create a k8s pod resource with [Pulumi k8s provider](https://www.pulumi.com/registry/packages/kubernetes/).
4 |
5 | ### Connect to your K8s cluster in env0
6 | In order to apply this resource as an env0 [Pulumi template](https://docs.env0.com/docs/pulumi), you'll have to first connect to your cluster in env0.
7 | It can be easily done by following our [Kubernetes integration guide](https://docs.env0.com/docs/connect-your-cloud-account#kubernetes).
8 |
9 | ### Setting the k8s provider
10 | When you use our [Kubernetes integration](https://docs.env0.com/docs/connect-your-cloud-account#kubernetes) we create a kubeconfig file for you in the default location `~/.kube/config`.
11 | Pulumi, by default, will look for a kubeconfig file in that location when using the Pulumi provider configuration:
12 |
13 | ```typescript
14 | let provider = new k8s.Provider("k8s-provider");
15 | ```
--------------------------------------------------------------------------------
/kubernetes/using-pulumi/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | setupVariables:
6 | after:
7 | - npm i
8 | pulumiLogin:
9 | before:
10 | - pulumi version
11 |
12 | destroy:
13 | steps:
14 | setupVariables:
15 | after:
16 | - npm i
17 | pulumiLogin:
18 | before:
19 | - pulumi version
--------------------------------------------------------------------------------
/kubernetes/using-pulumi/index.ts:
--------------------------------------------------------------------------------
1 | import * as k8s from "@pulumi/kubernetes";
2 |
3 | // Create a Kubernetes provider without specifying a kubeconfig
4 | // It automatically uses the default kubeconfig on your machine
5 | let provider = new k8s.Provider("k8s-provider");
6 |
7 | // uses the created provider to create an Nginx pod
8 | let pod = new k8s.core.v1.Pod("my-nginx", {
9 | metadata: {
10 | name: "my-nginx",
11 | },
12 | spec: {
13 | containers: [{
14 | name: "my-nginx",
15 | image: "nginx",
16 | }],
17 | },
18 | }, { provider });
19 |
20 | // Export the name of the Pod
21 | export const podName = pod.metadata;
--------------------------------------------------------------------------------
/kubernetes/using-pulumi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "k8s-using-pulumi",
3 | "devDependencies": {
4 | "@types/node": "^8.0.0"
5 | },
6 | "dependencies": {
7 | "@pulumi/pulumi": "latest",
8 | "@pulumi/kubernetes": "latest"
9 | }
10 | }
--------------------------------------------------------------------------------
/kubernetes/using-pulumi/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "bin",
4 | "target": "es2016",
5 | "module": "commonjs",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "experimentalDecorators": true,
9 | "pretty": true,
10 | "noFallthroughCasesInSwitch": true,
11 | "noImplicitAny": true,
12 | "noImplicitReturns": true,
13 | "forceConsistentCasingInFileNames": true,
14 | "strictNullChecks": true
15 | },
16 | "files": [
17 | "index.ts"
18 | ]
19 | }
--------------------------------------------------------------------------------
/kubernetes/using-terraform/README.md:
--------------------------------------------------------------------------------
1 | # Kubernetes Using Terraform
2 |
3 | Create a k8s pod resource with [Terraform k8s provider](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs).
4 |
5 | ### Connect to your K8s cluster in env0
6 | In order to apply this resource as an env0 [Terraform template](https://docs.env0.com/docs/templates#terraform), you'll have to first connect to your cluster in env0.
7 | It can be easily done by following our [Kubernetes integration guide](https://docs.env0.com/docs/connect-your-cloud-account#kubernetes).
8 |
9 | ### Setting the k8s provider
10 | When you use our [Kubernetes integration](https://docs.env0.com/docs/connect-your-cloud-account#kubernetes) we create a kubeconfig file for you in the default location `~/.kube/config`.
11 | You can easily use this kubeconfig file with the k8s provider by using the following Terraform provider configuration:
12 |
13 | ```hcl
14 | provider "kubernetes" {
15 | config_path = "~/.kube/config"
16 | }
17 | ```
--------------------------------------------------------------------------------
/kubernetes/using-terraform/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_providers {
3 | kubernetes = {
4 | source = "hashicorp/kubernetes"
5 | }
6 | }
7 | }
8 |
9 | provider "kubernetes" {
10 | config_path = "~/.kube/config"
11 | }
12 |
13 | resource "kubernetes_deployment" "nginx" {
14 | metadata {
15 | name = "scalable-nginx-example"
16 | labels = {
17 | App = "ScalableNginxExample"
18 | }
19 | }
20 |
21 | spec {
22 | replicas = 2
23 | selector {
24 | match_labels = {
25 | App = "ScalableNginxExample"
26 | }
27 | }
28 | template {
29 | metadata {
30 | labels = {
31 | App = "ScalableNginxExample"
32 | }
33 | }
34 | spec {
35 | container {
36 | image = "nginx:1.7.8"
37 | name = "example"
38 |
39 | port {
40 | container_port = 80
41 | }
42 |
43 | resources {
44 | limits = {
45 | cpu = "0.5"
46 | memory = "512Mi"
47 | }
48 | requests = {
49 | cpu = "250m"
50 | memory = "50Mi"
51 | }
52 | }
53 | }
54 | }
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/misc/ansible/playbook.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Debug
3 | hosts: localhost
4 | tasks:
5 | - name: Msg
6 | debug:
7 | msg: "hello"
8 |
--------------------------------------------------------------------------------
/misc/azure-vault-sensitive-var/README.md:
--------------------------------------------------------------------------------
1 | This template validates that sensitive variables stored in azure vault are taken correctly during deployment.
2 | Relevant for self hosted agents only.
3 |
4 | It specifically validates that `$AZURE_SHAG_FAKE_SECRET`'s value is `FAKE_NEWS`
5 |
--------------------------------------------------------------------------------
/misc/azure-vault-sensitive-var/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | setupVariables:
6 | after:
7 | - chmod +x validate.sh
8 | - ./validate.sh
9 |
--------------------------------------------------------------------------------
/misc/azure-vault-sensitive-var/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
3 |
--------------------------------------------------------------------------------
/misc/azure-vault-sensitive-var/validate.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 | if [[ "$AZURE_SHAG_FAKE_SECRET" == "FAKE_NEWS" ]];
4 | then
5 | echo "Loaded secret from azure vault successfully"
6 | exit 0
7 | else
8 | echo "Validation failed! Value of azure vault secret is $AZURE_SHAG_FAKE_SECRET"
9 | exit 1
10 | fi
11 |
--------------------------------------------------------------------------------
/misc/clone-with-commit-integ-test/env0.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | deploy:
3 | steps:
4 | setupVariables:
5 | after:
6 | - name: "Compare revisions"
7 | run: |
8 | #!/bin/bash
9 |
10 | # Ensure that the script exits on any error
11 | set -e
12 |
13 | # Get the current git revision
14 | current_revision=$(git rev-parse HEAD)
15 |
16 | echo "current revision: $current_revision"
17 | echo "env0 revision: $ENV0_DEPLOYMENT_REVISION"
18 |
19 | # Compare the current git revision with the ENV0_DEPLOYMENT_REVISION
20 | if [ "$current_revision" != "$ENV0_DEPLOYMENT_REVISION" ]; then
21 | echo "Error: Current git revision ($current_revision) does not match ENV0_DEPLOYMENT_REVISION ($ENV0_DEPLOYMENT_REVISION)." >&2
22 | exit 1
23 | fi
24 |
--------------------------------------------------------------------------------
/misc/clone-with-commit-integ-test/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
3 |
--------------------------------------------------------------------------------
/misc/custom-flow-tf-vars/README.md:
--------------------------------------------------------------------------------
1 | ### Custom Flow TF_VAR
2 |
3 | This template will output a TF_VAR that was defined using `$ENV0_ENV`
4 |
--------------------------------------------------------------------------------
/misc/custom-flow-tf-vars/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | terraformInit:
6 | before:
7 | - echo TF_VAR_email=user@domain.com >> $ENV0_ENV
8 |
--------------------------------------------------------------------------------
/misc/custom-flow-tf-vars/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
3 |
4 | variable "email" {
5 | type = string
6 | description = "env variable exported in env0.yml"
7 | default = "default@domain.com"
8 | }
9 |
10 | output "custom_flow_tf_var" {
11 | value = var.email
12 | }
13 |
--------------------------------------------------------------------------------
/misc/custom-flows-environment-variables/README.md:
--------------------------------------------------------------------------------
1 | # Env0 System Environment Variables
2 |
3 | This folder will deploy `null-resource` environment to `env0`
4 | and will also `echo` environment variables defined by the user in a different step than the one they ae printed on
5 |
--------------------------------------------------------------------------------
/misc/custom-flows-environment-variables/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | terraformPlan:
6 | before:
7 | - echo USER_NAME=user >> $ENV0_ENV
8 | - echo FULL_NAME_WITH_WHITESPACE=\"John Doe\" >> $ENV0_ENV
9 | - ./export-user-id.sh
10 | - echo "Populating ENV0_TERRAFORM_CONFIG_FILE_PATH - will be tested in main.tf to find an actual variable"
11 | - echo ENV0_TERRAFORM_CONFIG_FILE_PATH=var-file.json >> $ENV0_ENV
12 | after:
13 | - echo $USER_NAME
14 | - echo $FULL_NAME_WITH_WHITESPACE
15 | - ./print-user-id.sh
16 | - echo IN_SAME_STEP=works >> $ENV0_ENV
17 | - echo "****** Asserting expected values..."
18 | - "[ $USER_NAME == user ]"
19 | - '[ "$FULL_NAME_WITH_WHITESPACE" == "John Doe" ]'
20 | - "[ $USER_ID == user_id ]"
21 | - "[ $IN_SAME_STEP == works ]"
22 | - "[ $ENV0_TERRAFORM_CONFIG_FILE_PATH == var-file.json ]"
23 | destroy:
24 | steps:
25 | terraformPlan:
26 | before:
27 | - echo ENV0_TERRAFORM_CONFIG_FILE_PATH=var-file.json >> $ENV0_ENV
28 |
--------------------------------------------------------------------------------
/misc/custom-flows-environment-variables/export-user-id.sh:
--------------------------------------------------------------------------------
1 | echo USER_ID=user_id >> $ENV0_ENV
2 |
--------------------------------------------------------------------------------
/misc/custom-flows-environment-variables/main.tf:
--------------------------------------------------------------------------------
1 | variable "my-mandatory-var" {
2 | description = "This is mandatory and we will set it up using a magic var instantiated from a custom flow"
3 | }
4 |
5 | resource "null_resource" "null" {
6 | }
7 |
--------------------------------------------------------------------------------
/misc/custom-flows-environment-variables/print-user-id.sh:
--------------------------------------------------------------------------------
1 | echo $USER_ID
2 |
--------------------------------------------------------------------------------
/misc/custom-flows-environment-variables/var-file.json:
--------------------------------------------------------------------------------
1 | {
2 | "my-mandatory-var": "this is the value of the Mandalorian var"
3 | }
4 |
--------------------------------------------------------------------------------
/misc/decode-oidc/decode-oidc-token.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | decode_base64() {
4 | local len=$((${#1} % 4))
5 | local result="$1"
6 | if [ $len -eq 2 ]; then result="$1"'=='
7 | elif [ $len -eq 3 ]; then result="$1"'='
8 | fi
9 | echo "$result" | tr '_-' '/+' | base64 -d
10 | }
11 |
12 | decode_jwt(){
13 | decode_base64 $(echo -n $2 | cut -d "." -f $1) | jq .
14 | }
15 |
16 | decode_jwt 1 $ENV0_OIDC_TOKEN
17 |
18 | # Decode JWT Payload
19 | decode_jwt 2 $ENV0_OIDC_TOKEN
20 |
--------------------------------------------------------------------------------
/misc/decode-oidc/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | terraformPlan:
6 | before:
7 | # Check tools permissions
8 | - ./decode-oidc-token.sh
9 |
10 |
--------------------------------------------------------------------------------
/misc/decode-oidc/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
3 |
4 |
--------------------------------------------------------------------------------
/misc/drift-detection/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | terraformApply:
6 | after:
7 | - rm foo.bar
8 |
9 |
--------------------------------------------------------------------------------
/misc/drift-detection/main.tf:
--------------------------------------------------------------------------------
1 | resource "local_file" "foo" {
2 | content = "foo!"
3 | filename = "${path.module}/foo.bar"
4 | }
5 |
--------------------------------------------------------------------------------
/misc/ensure-permissions-on-tools-and-folders-for-user-node/ensure-permissions.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e -x
3 |
4 | # list installed apk packages
5 | apk list --installed
6 |
7 | # list installed python packages
8 | pip3 list
9 |
10 | # from base image
11 | node --version
12 | npm --version
13 | yarn --version
14 |
15 | #from alpine repos
16 | bash --version
17 | git --version
18 | python3 --version
19 | pip3 --version
20 | jq --version
21 | openssl version
22 | ssh -V
23 | curl --version
24 |
25 | # other
26 | aws --version
27 | awsv2 --version
28 | gcloud --version
29 | az --version
30 | kubectl version --client
31 | tfenv --version
32 | terraform --version
33 | tgenv --version
34 | terratag --help
35 | pwsh -v
36 | infracost --version
37 | helm version
38 |
39 | # Check write permissions
40 | touch /opt/test
41 | rm /opt/test
42 | touch /tmp/test
43 | rm /tmp/test
44 | touch /home/node/test
45 | rm /home/node/test
46 | mkdir -p /home/node/.cache
47 | python3 -m venv -h
48 | helm repo add env0 https://env0.github.io/self-hosted
49 | helm repo update
50 | helm show chart env0/env0-agent
51 |
52 | # Check packages install
53 | pip install --break-system-packages --user ansible
54 | ansible --version
55 |
56 | sudo apk add --no-cache rsync
57 | rsync --version
58 |
59 | sudo npm install -g @env0/cli
60 | env0 help
61 |
--------------------------------------------------------------------------------
/misc/ensure-permissions-on-tools-and-folders-for-user-node/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | terraformPlan:
6 | before:
7 | # Check tools permissions
8 | - ./ensure-permissions.sh
9 |
10 |
--------------------------------------------------------------------------------
/misc/ensure-permissions-on-tools-and-folders-for-user-node/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
3 |
4 |
--------------------------------------------------------------------------------
/misc/environment-outputs/inputs/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | setupVariables:
6 | after:
7 | - chmod +x validate.sh
8 | - ./validate.sh
9 |
--------------------------------------------------------------------------------
/misc/environment-outputs/inputs/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
3 |
--------------------------------------------------------------------------------
/misc/environment-outputs/inputs/validate.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 | if [[ "$SENSITIVE" == "sensitive" ]];
4 | then
5 | echo "Resolved SENSITIVE input correctly"
6 | else
7 | echo "Didnt resolve SENSITIVE input correctly, got - $SENSITIVE"
8 | exit 1
9 | fi
10 |
11 | if [[ "$NOT_SENSITIVE" == "not sensitive" ]];
12 | then
13 | echo "Resolved NOT_SENSITIVE input correctly"
14 | else
15 | echo "Didnt resolve NOT_SENSITIVE input correctly, got - $NOT_SENSITIVE"
16 | exit 1
17 | fi
18 |
--------------------------------------------------------------------------------
/misc/environment-outputs/outputs/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
3 |
4 | output "not_sensitive_output" {
5 | value = "not sensitive"
6 | }
7 |
8 |
9 | output "sensitive_output" {
10 | value = "sensitive"
11 | sensitive = true
12 | }
13 |
--------------------------------------------------------------------------------
/misc/environment-variables/README.md:
--------------------------------------------------------------------------------
1 | # Env0 System Environment Variables
2 |
3 | This folder will deploy `null-resource` environment to `env0`
4 | and will also `echo` our system environment variables that we currently support
5 | ```shell
6 | ENV0_ENVIRONMENT_ID
7 | ENV0_PROJECT_ID
8 | ENV0_DEPLOYMENT_LOG_ID
9 | ENV0_WORKSPACE_NAME
10 | ENV0_ORGANIZATION_ID
11 | ENV0_TEMPLATE_ID
12 | ENV0_TEMPLATE_NAME
13 | ENV0_ENVIRONMENT_NAME
14 | ENV0_ENVIRONMENT_CREATOR_NAME
15 | ENV0_ENVIRONMENT_CREATOR_EMAIL
16 | ENV0_DEPLOYER_NAME
17 | ENV0_DEPLOYER_EMAIL
18 | ```
19 |
--------------------------------------------------------------------------------
/misc/environment-variables/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | terraformPlan:
6 | before:
7 | - echo $ENV0_ENVIRONMENT_ID
8 | - echo $ENV0_PROJECT_ID
9 | - echo $ENV0_DEPLOYMENT_LOG_ID
10 | - echo $ENV0_WORKSPACE_NAME
11 | - echo $ENV0_ORGANIZATION_ID
12 | - echo $ENV0_TEMPLATE_ID
13 | - echo $ENV0_TEMPLATE_NAME
14 | - echo $ENV0_ENVIRONMENT_NAME
15 | - echo $ENV0_ENVIRONMENT_CREATOR_NAME
16 | - echo $ENV0_ENVIRONMENT_CREATOR_EMAIL
17 | - echo $ENV0_DEPLOYER_NAME
18 | - echo $ENV0_DEPLOYER_EMAIL
19 |
--------------------------------------------------------------------------------
/misc/environment-variables/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
3 |
--------------------------------------------------------------------------------
/misc/git-submodules/https/README.md:
--------------------------------------------------------------------------------
1 | # Git Modules
2 | This is an example of using [Git Modules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) defined via `.gitmodules` (unlike terraform module) using hard coded https path.
3 |
4 |
--------------------------------------------------------------------------------
/misc/git-submodules/relative/README.md:
--------------------------------------------------------------------------------
1 | # Git Modules
2 | This is an example of using [Git Modules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) defined via `.gitmodules` (unlike terraform module) as path **relative** to the **repository** as describe [here](https://git-scm.com/docs/git-submodule#_commands).
3 |
4 |
--------------------------------------------------------------------------------
/misc/local-sub-module/child/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
3 |
--------------------------------------------------------------------------------
/misc/local-sub-module/parent/main.tf:
--------------------------------------------------------------------------------
1 | module "remote-module" {
2 | source = "../child"
3 | }
4 |
--------------------------------------------------------------------------------
/misc/null-fail-by-variable/README.md:
--------------------------------------------------------------------------------
1 | A template used to simulate a failure using the `SHOULD_PASS` environment variable.
--------------------------------------------------------------------------------
/misc/null-fail-by-variable/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 | deploy:
3 | steps:
4 | setupVariables:
5 | after:
6 | - if [ -z "$SHOULD_PASS" ]; then echo "SHOULD_PASS must be supplied" 1>&2 && exit 1; fi
--------------------------------------------------------------------------------
/misc/null-fail-by-variable/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
--------------------------------------------------------------------------------
/misc/null-resource-with-tf-version-constraints/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.2.0, < 2.0.0"
3 | }
4 | resource "null_resource" "null" {
5 | }
6 |
--------------------------------------------------------------------------------
/misc/null-resource-workflow-environment/README.md:
--------------------------------------------------------------------------------
1 | ## What is this?
2 |
3 | Very simple workflow that deploy two environments from `null-resource` template
4 |
--------------------------------------------------------------------------------
/misc/null-resource-workflow-environment/env0.workflow.yml:
--------------------------------------------------------------------------------
1 | environments:
2 | first-alias:
3 | name: first-name
4 | templateName: 'null-resource-1'
5 | second-alias:
6 | name: second-name
7 | templateName: 'null-resource-2'
8 | needs: [ first-alias ]
9 |
--------------------------------------------------------------------------------
/misc/null-resource/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
3 |
--------------------------------------------------------------------------------
/misc/null-sleep/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | setupVariables:
6 | after:
7 | - sleep ${SLEEP_IN_SECONDS:-60}
8 |
--------------------------------------------------------------------------------
/misc/null-sleep/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
3 |
--------------------------------------------------------------------------------
/misc/remote-backend-on-s3/env0.yml:
--------------------------------------------------------------------------------
1 | deploy:
2 | steps:
3 | terraformInit:
4 | before:
5 | - aws s3api create-bucket --bucket env0-tf-remote-backend-bucket --region us-east-1
6 |
--------------------------------------------------------------------------------
/misc/remote-backend-on-s3/main.tf:
--------------------------------------------------------------------------------
1 | provider "aws" {
2 | version = "~> 2.0"
3 | region = "us-east-1"
4 | }
5 |
6 | terraform {
7 | backend "s3" {
8 | bucket = "env0-tf-remote-backend-bucket"
9 | key = "remote-backend"
10 | region = "us-east-1"
11 | }
12 | }
13 |
14 | resource "null_resource" "null" {
15 | }
16 |
--------------------------------------------------------------------------------
/misc/remote-backend/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | terraformApply:
6 | after:
7 | - chmod 700 ./validate-remote.sh
8 | - ./validate-remote.sh
9 |
--------------------------------------------------------------------------------
/misc/remote-backend/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null-resource" {
2 |
3 | }
4 |
--------------------------------------------------------------------------------
/misc/remote-backend/validate-remote.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | EXPECTED_TYPE='remote'
4 | ACTUAL_TYPE=$(cat .terraform/terraform.tfstate | jq -r ".backend.type")
5 | echo "Actual backend type: $ACTUAL_TYPE"
6 | if [[ "$EXPECTED_TYPE" == "$ACTUAL_TYPE" ]];
7 | then
8 | echo 'backend type is remote. OK'
9 | exit 0
10 | else
11 | echo 'backend type is not remote. FAILED'
12 | exit 1
13 | fi
14 |
--------------------------------------------------------------------------------
/misc/single-environment-workflow/README.md:
--------------------------------------------------------------------------------
1 | ## What is this?
2 |
3 | This is an example of a workflow template with one environment.
4 | In this specific scenario:
5 | - Deployment would start deployment of one null-resource stack `nullService1`
6 |
7 | ## How to run in env0?
8 |
9 | ### Prerequisites
10 |
11 | This example assumes the template with the following name already exist on your env0 organisation:
12 | - 'null resource'
13 |
14 | You can either create it in your organization, or alter `env0.workflow.yml` file to match other existing templates in your env0 organisation
15 |
16 | ### Defining the template
17 |
18 | - In env0, create a new template of type "env0 workflow"
19 | - On the VCS step, pick the repository containing this file, and put `misc/single-environment-workflow` under "env0 Workflow Location"
20 | - Save the template
21 |
22 | ### Running the template
23 |
24 | Now that the template is defined, you can simply run it in any env0 project using the "Create New Environment" button.
25 | Make sure to pick the template defined in the last step
26 |
--------------------------------------------------------------------------------
/misc/single-environment-workflow/env0.workflow.yml:
--------------------------------------------------------------------------------
1 | environments:
2 | rootService1:
3 | name: nullService1
4 | templateName: 'null resource'
5 |
--------------------------------------------------------------------------------
/misc/slack-notification/README.md:
--------------------------------------------------------------------------------
1 | # Env0 Deployment Slack Notifications
2 |
3 | Sends a Slack message for multiple events:
4 | * Deploy start
5 | * Destroy start
6 | * Found changes (terraform plan)
7 | * Deploy failed
8 | * Destroy failed
9 | * Waiting for approval
10 | * Deploy approved
11 | * Destroy approved
12 |
13 | For this to work the following environment variables should be provided:
14 |
15 | * `SLACK_URL` - The webhook url to post to (found in [Slack](https://env0.slack.com/apps/A0F7XDUAZ-incoming-webhooks))
16 |
--------------------------------------------------------------------------------
/misc/slack-notification/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | setupVariables:
6 | after:
7 | - ./on-start.sh
8 | terraformPlan:
9 | after:
10 | - ./on-plan.sh
11 | terraformApply:
12 | before:
13 | - ./on-approve.sh
14 | storeState:
15 | after:
16 | - ./on-store-state.sh
17 | onSuccess:
18 | - ./on-success.sh
19 | onFailure:
20 | - ./on-fail.sh
21 |
22 | destroy:
23 | steps:
24 | setupVariables:
25 | after:
26 | - ./on-start.sh
27 | terraformPlan:
28 | after:
29 | - ./on-plan.sh
30 | terraformDestroy:
31 | before:
32 | - ./on-approve.sh
33 | onSuccess:
34 | - ./on-success.sh
35 | onFailure:
36 | - ./on-fail.sh
37 |
--------------------------------------------------------------------------------
/misc/slack-notification/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
3 |
--------------------------------------------------------------------------------
/misc/slack-notification/on-approve.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if [[ -n "${ENV0_REVIEWER_NAME}" ]]; then
4 | MESSAGE="\`${ENV0_DEPLOYMENT_TYPE}\` deployment approved by: \`${ENV0_REVIEWER_NAME} (${ENV0_REVIEWER_EMAIL})\`"
5 |
6 | __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7 | source "${__dir}"/slack.sh "$MESSAGE"
8 | fi
9 |
10 | touch apply_ran_successfully
11 |
--------------------------------------------------------------------------------
/misc/slack-notification/on-fail.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | MESSAGE="Failed running \`${ENV0_DEPLOYMENT_TYPE}\` deployment."
4 |
5 | __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6 | source "${__dir}"/slack.sh "$MESSAGE"
7 |
--------------------------------------------------------------------------------
/misc/slack-notification/on-plan.sh:
--------------------------------------------------------------------------------
1 | DIFFERENCE=$(terraform show -json .tf-plan | jq '.resource_changes[] | select(.| .change.actions[0] != "no-op")')
2 |
3 | if [[ -z "${DIFFERENCE}" ]]; then
4 | echo "No changes in terraform plan"
5 | else
6 | __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7 | source "${__dir}"/slack.sh "Found changes in terraform plan"
8 | fi
9 |
--------------------------------------------------------------------------------
/misc/slack-notification/on-start.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if [[ -z "${ENV0_REVIEWER_NAME}" ]]; then
4 | ACTION="Started"
5 | else
6 | ACTION="Continued"
7 | fi
8 |
9 | if [ "${ENV0_DEPLOYER_NAME}" = "env0" ]; then
10 | TRIGGER="System"
11 | else
12 | TRIGGER="Manual"
13 | fi
14 |
15 | MESSAGE="${ACTION} running \`${ENV0_DEPLOYMENT_TYPE}\` deployment.\nTrigger: ${TRIGGER} Run"
16 |
17 | __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18 | source "${__dir}"/slack.sh "$MESSAGE"
19 |
20 | rm -f apply_ran_successfully
21 |
--------------------------------------------------------------------------------
/misc/slack-notification/on-store-state.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
4 |
5 | if [ -f apply_ran_successfully ]; then
6 | echo 'apply step ran, not waiting for approval'
7 | else
8 | MESSAGE="Environment \`${ENV0_ENVIRONMENT_NAME}\` is waiting for approval."
9 | source "${__dir}"/slack.sh "$MESSAGE"
10 | fi
11 |
--------------------------------------------------------------------------------
/misc/slack-notification/on-success.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | MESSAGE="Successfully finished running \`${ENV0_DEPLOYMENT_TYPE}\` deployment."
4 |
5 | __dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6 | source "${__dir}"/slack.sh "$MESSAGE"
7 |
--------------------------------------------------------------------------------
/misc/slack-notification/slack.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if [[ -z "${ENV0_DEPLOYMENT_REVISION}" ]]; then
4 | REVISION="repository's default branch"
5 | else
6 | REVISION=$ENV0_DEPLOYMENT_REVISION
7 | fi
8 |
9 | DEPLOYMENT_DETAILS=""
10 |
11 | MESSAGE=":rocket: :information_source: ${DEPLOYMENT_DETAILS} - ${1}"
12 | ICON_URL="https://uploads-ssl.webflow.com/5ceab5395d0f478e169de7c0/5f21eb54b57c7a8559c68ff7_Env0-Color%20Icon%403x.png"
13 |
14 | PAYLOAD="{\"username\": \"env0\", \"text\": \"${MESSAGE}\", \"icon_url\": \"${ICON_URL}\"}"
15 |
16 | curl -X POST --data-urlencode "payload=${PAYLOAD}" "${SLACK_URL}"
17 |
--------------------------------------------------------------------------------
/misc/ssm-sensitive-var/README.md:
--------------------------------------------------------------------------------
1 | This template validates that sensitive variable accessed via SSM are taken correctly during deployment.
2 | Relevant for self hosted agents only.
3 |
4 | It specifically validates that `$SHAG_FAKE_SECRET`'s value is `FAKE_NEWS`
5 |
--------------------------------------------------------------------------------
/misc/ssm-sensitive-var/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | setupVariables:
6 | after:
7 | - chmod +x validate.sh
8 | - ./validate.sh
9 |
--------------------------------------------------------------------------------
/misc/ssm-sensitive-var/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null1" {
2 | }
3 |
--------------------------------------------------------------------------------
/misc/ssm-sensitive-var/validate.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 | if [[ "$SHAG_FAKE_SECRET" == "FAKE_NEWS" ]];
4 | then
5 | echo "Loaded secret from SSM successfully"
6 | exit 0
7 | else
8 | echo "Validation failed! Value of SSM secret is $SHAG_FAKE_SECRET"
9 | exit 1
10 | fi
11 |
--------------------------------------------------------------------------------
/misc/terraform-validate-workspace/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.15.1"
3 | }
4 |
5 | resource "null_resource" "null" {
6 | count = terraform.workspace == "default" ? -1 : 0 # This is used to check that the workspace in "terraform validate" isn't the default one
7 | }
8 |
--------------------------------------------------------------------------------
/misc/validate-assume-role/README.md:
--------------------------------------------------------------------------------
1 | ### Validate Assume Role
2 |
3 | This template validates that an assumed AWS IAM role has been assumed correctly by env0.
4 | It will validate that the assumed identity ARN matches the regex given in the environment variable `EXPECTED_ARN`
5 |
--------------------------------------------------------------------------------
/misc/validate-assume-role/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | setupVariables:
6 | after:
7 | - ./validate.sh
8 |
--------------------------------------------------------------------------------
/misc/validate-assume-role/main.tf:
--------------------------------------------------------------------------------
1 | resource "null_resource" "null" {
2 | }
3 |
--------------------------------------------------------------------------------
/misc/validate-assume-role/validate.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 |
4 | if [[ "$EXPECTED_ARN" == "" ]]
5 | then
6 | echo "Missing var EXPECTED_ARN"
7 | exit 1
8 | fi
9 |
10 | export ASSUMED_ARN=$(aws sts get-caller-identity --query Arn)
11 |
12 | echo "Assumed Role $ASSUMED_ARN"
13 |
14 | if [[ ! "$ASSUMED_ARN" =~ "$EXPECTED_ARN" ]]
15 | then
16 | echo "Assumed role expectation failed"
17 | exit 1
18 | fi
19 |
20 | echo "Assumed role expectation passed"
21 |
--------------------------------------------------------------------------------
/misc/validate-state/env0.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 |
3 | deploy:
4 | steps:
5 | terraformPlan:
6 | after:
7 | - ./validate.sh
8 |
--------------------------------------------------------------------------------
/misc/validate-state/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = "0.12.24"
3 | }
4 |
5 | resource "null_resource" "null1" {
6 | }
7 |
8 | resource "null_resource" "null2" {
9 | }
10 |
--------------------------------------------------------------------------------
/misc/validate-state/validate.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 | if [[ "$IS_REDEPLOY" == "true" ]];
4 | then
5 | EXPECTED_PLAN_OUTPUT="Plan: 0 to add, 0 to change, 0 to destroy."
6 | PLAN_OUTPUT=$(terraform show -no-color .tf-plan | tail -1)
7 | if [[ "$PLAN_OUTPUT" == "$EXPECTED_PLAN_OUTPUT" ]];
8 | then
9 | echo "Redeploy plan is OK"
10 | exit 0
11 | else
12 | echo "Validation Failed, Redeploy plan is $PLAN_OUTPUT";
13 | exit 1
14 | fi
15 | else
16 | echo "Not Redeploy so not validating"
17 | fi
18 |
--------------------------------------------------------------------------------
/misc/vault-integration/README.md:
--------------------------------------------------------------------------------
1 | ### Vault Integration test template
2 |
3 | - This template runs a Hashicorp Vault _client_ that's meant to test the JWT integration with a running Vault server instance.
4 | - It runs the `vault.sh` script which authenticates against vault.
5 | - `VAULT_ROLE`, `VAULT_NAMESPACE`, `VAULT_ADDR`, `VAULT_DEV_ROOT_TOKEN` - these should be supplied as env vars to the deployment. See `aws/vault-server-on-eks/README.md` for more info.
6 |
--------------------------------------------------------------------------------
/misc/vault-integration/configure-vault.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | echo "Installing vault client..."
5 |
6 | curl -sL https://releases.hashicorp.com/vault/1.11.1/vault_1.11.1_linux_amd64.zip -o vault1.zip
7 | unzip -o vault1.zip
8 | ./vault --version
9 |
10 | # The token should only be used to configure vault - after that we will login using OIDC
11 | export VAULT_TOKEN=$VAULT_DEV_ROOT_TOKEN
12 |
13 | # Cleaning up anything previously configured
14 | ./vault secrets disable secrets-for-env0/ || true
15 | ./vault auth disable env0-jwt/ || true
16 |
17 | # Configuring vault
18 | ./vault secrets enable -path=secrets-for-env0/ kv
19 |
20 | # # Bound a ACL policy for permissions
21 | ./vault policy write env0-access - <
2 |
3 |
4 |
5 | Hello from env0!
6 |
7 |
8 |
37 |
38 |
39 |
40 |
41 |
Welcome to your own environment !!!USER!!!
42 |
43 |

44 |
51 |
52 |
53 |
54 |