diff --git a/.github/workflows/fablab-db-creation.yml b/.github/workflows/fablab-db-creation.yml new file mode 100644 index 000000000..3f1cce1e0 --- /dev/null +++ b/.github/workflows/fablab-db-creation.yml @@ -0,0 +1,61 @@ +name: fablab db-creation workflow + +on: + workflow_dispatch: + push: + branches: + - main +env: + GOFLAGS: "-trimpath" + GOX_OUTPUT: "release/{{.Arch}}/{{.OS}}/{{.Dir}}" + GOX_TEST_OUTPUT: "test/{{.Arch}}/{{.OS}}/bin/{{.Dir}}" + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: "us-east-1" + gh_ci_key: ${{ secrets.GH_CI_KEY }} + S3_KEY: ${{ secrets.AWS_ACCESS_KEY_ID }} + S3_SECRET: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + +jobs: + build: + name: Build and Run + runs-on: ubuntu-latest + steps: + - name: Checkout ziti + uses: actions/checkout@v3 + with: + path: ziti + + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: '1.20.x' + + - name: Install Ziti CI + uses: openziti/ziti-ci@v1 + + - name: Configure Git + run: | + cd ziti + $(go env GOPATH)/bin/ziti-ci configure-git + + - name: Pull ZITI_VERSION and set as $GITHUB_ENV for use with fablab + run: | + cd ziti + version="$($(go env GOPATH)/bin/ziti-ci -q get-current-version)" + echo "Ziti Version: $version" + echo "ZITI_VERSION=$version" >> $GITHUB_ENV + + - name: Build and Run + run: | + cd ziti/zititest/models/db-creation + go build -o db-creation main.go + echo "ZITI_ROOT=$(go env GOPATH)/bin" >> "$GITHUB_ENV" + ./db-creation create db-creation + ./db-creation up + + - name: Teardown + if: always() + run: | + cd ziti/zititest/models/db-creation + ./db-creation dispose \ No newline at end of file diff --git a/common/getziti/github.go b/common/getziti/github.go index 229c3c445..e9dcee8ea 100644 --- a/common/getziti/github.go +++ b/common/getziti/github.go @@ -6,6 +6,7 @@ import ( "github.com/blang/semver" "github.com/go-resty/resty/v2" "github.com/michaelquigley/pfxlog" + "github.com/openziti/foundation/v2/versions" c "github.com/openziti/ziti/ziti/constants" "github.com/pkg/errors" "net/http" @@ -247,8 +248,17 @@ func InstallGitHubRelease(zitiApp string, release *GitHubReleasesData, binDir st if zitiApp == c.ZITI { count := 0 zitiFileName := "ziti-" + version + semVer, err := versions.ParseSemVer(version) + if err != nil { + return err + } + expectedPath := "ziti" + pathChangedVersion := versions.MustParseSemVer("0.29.0") + if semVer.CompareTo(pathChangedVersion) < 0 { + expectedPath = "ziti/ziti" + } err = UnTarGz(fullPath, binDir, func(path string) (string, bool) { - if path == "ziti/ziti" { + if path == expectedPath { count++ return zitiFileName, true } diff --git a/zititest/ami/README.md b/zititest/ami/README.md deleted file mode 100644 index 4f0bd3816..000000000 --- a/zititest/ami/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Ziti AMI - -This folder shows how to use [Packer](https://www.packer.io/) to create an [Amazon Machine -Image (AMI)](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html) that has the necessary prerequisites for running fablab based OpenZiti smoketests installed on top of Ubuntu 22.04. - -## Quick start - -To build the Ziti AMI: - -1. `git clone` this repo to your computer. -1. Install [Packer](https://www.packer.io/). -1. Configure your AWS credentials using one of the [options supported by the AWS - SDK](http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html). Usually, the easiest option is to - set the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables. -1. Run `packer build ziti-ami.pkr.hcl`. - -When the build finishes, it will output the ID of the new AMI. \ No newline at end of file diff --git a/zititest/ami/cleanup-old-images.sh b/zititest/ami/cleanup-old-images.sh deleted file mode 100755 index 0162bce93..000000000 --- a/zititest/ami/cleanup-old-images.sh +++ /dev/null @@ -1,18 +0,0 @@ -regions=( -"us-east-1" -"us-east-2" -"us-west-1" -"us-west-2" -"ca-central-1" -"ap-northeast-1" -"ap-southeast-2" -"sa-east-1" -"eu-central-1" -"af-south-1" -) - - -for region in ${regions[@]}; -do - aws ec2 describe-images --region ${region} --owners self --filters Name="name",Values="ziti-tests-*" | jq '[.Images[] | { Id: .ImageId, Date: .CreationDate}] | sort_by(.Date)' | jq -r '.[] | .Id ' | head -n -1 | xargs -t -r -n 1 aws ec2 deregister-image --region ${region} --image-id -done diff --git a/zititest/ami/etc/apt/apt.conf.d/99remote-not-fancy b/zititest/ami/etc/apt/apt.conf.d/99remote-not-fancy deleted file mode 100644 index ce12e07e0..000000000 --- a/zititest/ami/etc/apt/apt.conf.d/99remote-not-fancy +++ /dev/null @@ -1,2 +0,0 @@ -Binary::apt::APT::Color "0"; -Binary::apt::DPkg::Progress-Fancy "0"; \ No newline at end of file diff --git a/zititest/ami/etc/sysctl.d/51-network-tuning.conf b/zititest/ami/etc/sysctl.d/51-network-tuning.conf deleted file mode 100644 index edc76a389..000000000 --- a/zititest/ami/etc/sysctl.d/51-network-tuning.conf +++ /dev/null @@ -1,9 +0,0 @@ -# adjust the socket buffer sizes -net.core.rmem_max = 16777216 -net.core.wmem_max = 16777216 -net.core.rmem_default = 16777216 -net.core.wmem_default = 16777216 -net.ipv4.tcp_rmem = 4096 87380 16777216 -net.ipv4.tcp_wmem = 4096 65536 16777216 -net.ipv4.tcp_mem = 8388608 8388608 16777216 -net.ipv4.udp_mem = 8388608 8388608 16777216 \ No newline at end of file diff --git a/zititest/ami/etc/systemd/resolved.conf.d/ziti-tunnel.conf b/zititest/ami/etc/systemd/resolved.conf.d/ziti-tunnel.conf deleted file mode 100644 index 0f05e31cc..000000000 --- a/zititest/ami/etc/systemd/resolved.conf.d/ziti-tunnel.conf +++ /dev/null @@ -1,2 +0,0 @@ -[Resolve] -DNS=127.0.0.1 diff --git a/zititest/ami/list-images.sh b/zititest/ami/list-images.sh deleted file mode 100755 index 11c49393b..000000000 --- a/zititest/ami/list-images.sh +++ /dev/null @@ -1,11 +0,0 @@ -regions=( -"us-east-1" -"us-west-2" -) - - -for region in ${regions[@]}; -do - echo "Region: ${region}" - aws ec2 describe-images --region ${region} --owners self --filters Name="name",Values="ziti-tests-*" | jq '[.Images[] | { Id: .ImageId, Date: .CreationDate}] | sort_by(.Date)' | jq -r '.[] | (.Id + " " + .Date) ' -done diff --git a/zititest/ami/ziti-ami.pkr.hcl b/zititest/ami/ziti-ami.pkr.hcl deleted file mode 100644 index 295da7fe9..000000000 --- a/zititest/ami/ziti-ami.pkr.hcl +++ /dev/null @@ -1,76 +0,0 @@ -packer { - required_version = ">= 1.6.0" - - required_plugins { - amazon = { - version = ">= 1.1.1" - source = "github.com/hashicorp/amazon" - } - } -} - -source "amazon-ebs" "ziti-tests-ubuntu-ami" { - ami_description = "An Ubuntu AMI that has everything needed for running fablab smoketests." - ami_name = "ziti-tests-{{ timestamp }}" - ami_regions = ["us-east-1", "us-east-2", "us-west-1", "us-west-2", "ca-central-1", "ap-northeast-1", "ap-southeast-2", "sa-east-1", "eu-central-1", "af-south-1"] - instance_type = "t2.micro" - region = "us-east-1" - source_ami_filter { - filters = { - architecture = "x86_64" - name = "ubuntu/images/*/ubuntu-jammy-22.04-amd64-server-*" - root-device-type = "ebs" - virtualization-type = "hvm" - } - most_recent = true - owners = ["099720109477"] - } - ssh_username = "ubuntu" -} - -build { - sources = ["source.amazon-ebs.ziti-tests-ubuntu-ami"] - - provisioner "file" { - source = "etc/apt/apt.conf.d/99remote-not-fancy" - destination = "/home/ubuntu/99remote-not-fancy" - } - - provisioner "file" { - source = "etc/sysctl.d/51-network-tuning.conf" - destination = "/home/ubuntu/51-network-tuning.conf" - } - - provisioner "file" { - source = "etc/systemd/resolved.conf.d/ziti-tunnel.conf" - destination = "/home/ubuntu/ziti-tunnel.conf" - } - - provisioner "shell" { - inline = [ - "sudo mv /home/ubuntu/99remote-not-fancy /etc/apt/apt.conf.d/", - "sudo mv /home/ubuntu/51-network-tuning.conf /etc/sysctl.d/", - "sudo mkdir /etc/systemd/resolved.conf.d", - "sudo mv /home/ubuntu/ziti-tunnel.conf /etc/systemd/resolved.conf.d/", - "sudo chown root.root /etc/systemd/resolved.conf.d/*", - - "cloud-init status --wait", - - # add metricsbeat sources - "curl --fail --silent --show-error --location https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor | sudo dd of=/usr/share/keyrings/elasticsearch-archive-keyring.gpg", - "echo \"deb [arch=amd64 signed-by=/usr/share/keyrings/elasticsearch-archive-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main\" | sudo tee -a /etc/apt/sources.list.d/elastic-8.x.list", - - # add consul sources - "curl --fail --silent --show-error --location https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo dd of=/usr/share/keyrings/hashicorp-archive-keyring.gpg", - "echo \"deb [arch=amd64 signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main\" | sudo tee -a /etc/apt/sources.list.d/hashicorp.list", - - "sudo apt update", - "sudo apt upgrade -y", - "sudo apt install -y iperf3 tcpdump sysstat", - "sudo apt install -y metricbeat=8.3.2", - "sudo apt install -y consul", - "sudo bash -c \"echo 'ubuntu soft nofile 40960' >> /etc/security/limits.conf\"", - "sudo sed -i 's/ENABLED=\"false\"/ENABLED=\"true\"/g' /etc/default/sysstat", - ] - } -} diff --git a/zititest/models/db-creation/README.md b/zititest/models/db-creation/README.md new file mode 100644 index 000000000..b5f37c990 --- /dev/null +++ b/zititest/models/db-creation/README.md @@ -0,0 +1,50 @@ +# db-creation model + +### This model is designed to be used for GitHub Actions to create a test DB and export the pki/identities/DB to s3 buckets for later testing usage. ### + +- Only setup for AWS. +- Designed to work with the pete-iperf branch of fablab. +- You will need to supply your own keys/secrets. +- Infrastructure is configured in the main.go in the model. +- This is a very alpha release, minimal features. + +### There are several files that will likely need to be customized for your setup: ### + +- ziti/zititest/models/db-creation/main.go - mainly used to alter the model and also your Rsync and Disposal Actions (removing Route 53 A Record) +- ziti/zititest/models/db-creation/actions/bootstrap.go - This is where the meat of the actions take place. Sets up AWS remotely from the GH Runner (using Fablab executable), then runs the DB Creation Script. +- ziti/zititest/models/db-creation/resources/db_creator_script_external.sh - This is the script that interacts with Ziti and creates all the identities, services and policies. +- ziti/zititest/models/db-creation/resources/aws_setup.sh - This will default to us-east-1 region and use JSON output, if you want to change those values do that here. +- ziti/.github/workflows/fablab-db-creation.yml - This is where you will setup your GitHub workflow specifics, inserting your custom secret variable names, etc. As you can see at the end, the following 3 Fablab commands are all that is needed to run this: + - ```./db-creation create db-creation``` + - ```./db-creation up``` + - ```./db-creation dispose``` + +### Once the DB is saved in s3, you will need to pull that and the pki from the proper buckets via the following steps: + +#### Non Fablab import (manual) or something designed by you #### +- Make sure AWS CLI is configured on the machine you want the DB imported to. +- cd to the /home/ubuntu/fablab directory which is where the DB lies. +- Stop any existing Ziti processes. +- Simply delete the old DB file or rename it. +- Run the following AWS CLI command to import DB: + - ```aws s3 cp s3://db-bucket-name/ctrl.db-filename ctrl.db ``` +- Remove the contents of the entire pki directory using the following: + - ```cd pki``` + - ```sudo rm -rf *``` + - ```cd ..``` +- Run the following to import the pki directory (replacing pki-s3-bucket-name/pki-folder-name with your names) : + - ```aws s3 cp --recursive s3://pki-s3-bucket-name/pki-s3-folder-name/ pki/``` +- Run the following command while replacing the ziti version number in filename to start the controller: + - ```nohup /home/ubuntu/fablab/bin/ziti-v0.28.4 controller run --log-formatter pfxlog /home/ubuntu/fablab/cfg/ctrl.yml --cli-agent-alias ctrl > /home/ubuntu/logs/ctrl.log 2>&1 & ``` + +#### Fablab import #### +- cd into your local ziti/zititest/models/db-creation/resources folder and then import both the DB and PKI from your s3 buckets: + - Command to run for your DB import: + - ```aws s3 cp s3://s3-db-bucket-name/s3-ctrl.db-filename ctrl.db``` + - Commands to run for your PKI import: + - ```mkdir pki``` + - ```aws s3 cp --recursive s3://pki-s3-bucket-name/pki-s3-folder-name/ pki/``` +- Within your main.go for the db-creation model, you should uncomment the 2 following lines within the Distribution portion of the model, around line 123 or so: + - ```rsync.NewRsyncHost("#ctrl", "resources/ctrl.db", "/home/ubuntu/fablab/ctrl.db"),``` + - ```rsync.NewRsyncHost("#ctrl", "resources/pki/", "/home/ubuntu/fablab/pki/"),``` +- Now you should be able to create a fresh db-creation executable by building and run that, which should have the new DB/PKI. \ No newline at end of file diff --git a/zititest/models/db-creation/actions/bootstrap.go b/zititest/models/db-creation/actions/bootstrap.go new file mode 100644 index 000000000..c532913b5 --- /dev/null +++ b/zititest/models/db-creation/actions/bootstrap.go @@ -0,0 +1,178 @@ +/* + (c) Copyright NetFoundry Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package actions + +import ( + "encoding/json" + "fmt" + "github.com/openziti/fablab/kernel/lib/actions" + "github.com/openziti/fablab/kernel/lib/actions/component" + "github.com/openziti/fablab/kernel/lib/actions/host" + "github.com/openziti/fablab/kernel/lib/actions/semaphore" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/ziti/zititest/zitilab" + zitilib_actions "github.com/openziti/ziti/zititest/zitilab/actions" + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + "github.com/openziti/ziti/zititest/zitilab/models" + "os" + "time" +) + +const DomainName = "controller.testing.openziti.org" +const Create = "CREATE" +const Delete = "DELETE" + +type bootstrapAction struct{} + +// Define a struct to represent the nested "ResourceRecordSet" object +type ResourceRecordSet struct { + Name string `json:"Name"` + Type string `json:"Type"` + TTL int `json:"TTL"` + ResourceRecords []struct { + Value string `json:"Value"` + } `json:"ResourceRecords"` +} + +// Define a struct to represent the nested "Changes" object +type Change struct { + Action string `json:"Action"` + ResourceRecordSet ResourceRecordSet `json:"ResourceRecordSet"` +} + +// Define the main Payload struct to represent the entire JSON payload +type Payload struct { + Changes []Change `json:"Changes"` +} + +func NewBootstrapAction() model.ActionBinder { + action := &bootstrapAction{} + return action.bind +} + +func Route53StringCreator(m *model.Model, action string) string { + var payload = Payload{ + Changes: []Change{ + { + Action: action, + ResourceRecordSet: ResourceRecordSet{ + Name: DomainName, // The DNS record name + Type: "A", // Type A represents an IPv4 address + TTL: 300, // TTL value in seconds + ResourceRecords: []struct { + Value string `json:"Value"` + }{ + {Value: m.MustSelectHost("#ctrl").PublicIp}, + }, + }, + }, + }, + } + jsonData, err := json.MarshalIndent(payload, "", " ") + if err != nil { + fmt.Println("Error marshaling struct to JSON:", err) + } + dnsAddJsonData := string(jsonData) + s := "aws route53 change-resource-record-sets --hosted-zone-id Z09612893W445K5ME8MYS --change-batch '" + dnsAddJsonData + "'" + return s +} + +func (a *bootstrapAction) bind(m *model.Model) model.Action { + workflow := actions.Workflow() + // Set AWS config remotely + accessKey := os.Getenv("S3_KEY") + if accessKey != "" { + fmt.Println("S3_KEY", accessKey) + } else { + fmt.Println("S3_KEY missing") + } + accessSecret := os.Getenv("S3_SECRET") + if accessSecret != "" { + fmt.Println("S3_SECRET", accessSecret) + } else { + fmt.Println("S3_SECRET missing") + } + accessKeyIDString := "export AWS_ACCESS_KEY_ID=" + accessKey + accessSecretString := "export AWS_SECRET_ACCESS_KEY=" + accessSecret + setAccessKeyIDString := "aws configure set aws_access_key_id " + accessKey + setAccessSecretString := "aws configure set aws_secret_access_key " + accessSecret + workflow.AddAction(host.GroupExec("#ctrl", 1, accessKeyIDString)) + workflow.AddAction(host.GroupExec("#ctrl", 1, accessSecretString)) + workflow.AddAction(host.GroupExec("#ctrl", 1, setAccessKeyIDString)) + workflow.AddAction(host.GroupExec("#ctrl", 1, setAccessSecretString)) + workflow.AddAction(host.GroupExec("#ctrl", 1, "aws configure set default.region us-east-1")) + workflow.AddAction(host.GroupExec("#ctrl", 1, "aws configure set default.output json")) + + // Run aws_setup script - passing in AWS Key and Secret + awsScriptExecutionText := "sudo /home/ubuntu/fablab/bin/aws_setup.sh " + accessKey + " " + accessSecret + workflow.AddAction(host.GroupExec("#ctrl", 1, "sudo chmod 0755 /home/ubuntu/fablab/bin/aws_setup.sh")) + workflow.AddAction(host.GroupExec("#ctrl", 1, awsScriptExecutionText)) + + //Add Route53 DNS A Record + workflow.AddAction(model.ActionFunc(func(run model.Run) error { + m := run.GetModel() + s := Route53StringCreator(m, Create) + return host.Exec(m.MustSelectHost("#ctrl"), s).Execute(run) + })) + + //Start Ziti Controller + workflow.AddAction(host.GroupExec("#ctrl", 1, "rm -f logs/*")) + workflow.AddAction(component.Stop("#ctrl")) + workflow.AddAction(component.Exec("#ctrl", zitilab.ControllerActionInitStandalone)) + workflow.AddAction(component.Start("#ctrl")) + workflow.AddAction(edge.ControllerAvailable("#ctrl", 30*time.Second)) + + // Login to Ziti Controller + workflow.AddAction(edge.Login("#ctrl")) + workflow.AddAction(semaphore.Sleep(2 * time.Second)) + + // Setup Ziti Routers + workflow.AddAction(component.StopInParallel(models.EdgeRouterTag, 25)) + workflow.AddAction(edge.InitEdgeRouters(models.EdgeRouterTag, 2)) + workflow.AddAction(semaphore.Sleep(2 * time.Second)) + + // Init Identities + workflow.AddAction(edge.InitIdentities(models.SdkAppTag, 2)) + workflow.AddAction(semaphore.Sleep(2 * time.Second)) + + // Create Configs + workflow.AddAction(zitilib_actions.Edge("create", "config", "iperf-server", "host.v1", ` + { + "address" : "localhost", + "port" : 7001, + "protocol" : "tcp" + }`)) + workflow.AddAction(semaphore.Sleep(2 * time.Second)) + workflow.AddAction(zitilib_actions.Edge("create", "config", "iperf-intercept", "intercept.v1", ` + { + "addresses": ["iperf.service"], + "portRanges" : [ + { "low": 7001, "high": 7001 } + ], + "protocols": ["tcp"] + }`)) + workflow.AddAction(semaphore.Sleep(2 * time.Second)) + + // Start Beats Services + workflow.AddAction(host.GroupExec("ctrl", 25, "sudo service filebeat stop; sleep 5; sudo service filebeat start")) + workflow.AddAction(host.GroupExec("ctrl", 25, "sudo service metricbeat stop; sleep 5; sudo service metricbeat start")) + + // Run DB Creation Shell script + workflow.AddAction(host.GroupExec("ctrl", 1, "sudo chmod 0755 /home/ubuntu/fablab/bin/db_creator_script_external.sh")) + workflow.AddAction(host.GroupExec("ctrl", 1, "sudo /home/ubuntu/fablab/bin/db_creator_script_external.sh")) + return workflow +} diff --git a/zititest/models/db-creation/configs/ctrl.yml.tmpl b/zititest/models/db-creation/configs/ctrl.yml.tmpl new file mode 100644 index 000000000..8e2f46c7b --- /dev/null +++ b/zititest/models/db-creation/configs/ctrl.yml.tmpl @@ -0,0 +1,194 @@ +v: 3 + +db: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/ctrl.db + +identity: + cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/ctrl/certs/{{ .Component.Id }}-server.cert + key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/ctrl/keys/{{ .Component.Id }}-server.key + ca: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/ctrl/certs/{{ .Component.Id }}-server.chain.pem + +# the endpoint that routers will connect to the controller over. +ctrl: + listener: tls:0.0.0.0:6262 + options: + advertiseAddress: tls:{{.Host.PublicIp}}:6262 + # (optional) settings + # set the maximum number of connect requests that are buffered and waiting to be acknowledged (1 to 5000, default 1000) + #maxQueuedConnects: 50 + + # the maximum number of connects that have begun hello synchronization (1 to 1000, default 16) + #maxOutstandingConnects: 100 + + # the number of milliseconds to wait before a hello synchronization fails and closes the connection (30ms to 60000ms, default: 1000ms) + #connectTimeoutMs: 3000 + + # Sets the control channel write timeout. A write timeout will close the control channel, so the router will reconnect + #writeTimeout: 15s + + # A listener address which will be sent to connecting routers in order to change their configured controller + # address. If defined, routers will update address configuration to immediately use the new address for future + # connections. The value of newListener must be resolvable both via DNS and validate via certificates + #newListener: tls:localhost:6262 + +#events: +# jsonLogger: +# subscriptions: +# - type: fabric.routers +# - type: fabric.terminators +# - type: metrics +# sourceFilter: .* +# metricFilter: .*egress.*m1_rate* +# - type: fabric.circuits +# include: +# - created +# - type: edge.sessions +# include: +# - created +# - type: edge.apiSessions +# - type: fabric.usage +# - type: services +# - type: fabric.usage +# - type: edge.entityCounts +# interval: 5s +# handler: +# type: file +# format: json +# path: /tmp/ziti-events.log + +healthChecks: + boltCheck: + # How often to try entering a bolt read tx. Defaults to 30 seconds + interval: 30s + # When to timeout the check. Defaults to 15 seconds + timeout: 15s + # How long to wait before starting the check. Defaults to 15 seconds + initialDelay: 15s + +# By having an 'edge' section defined, the ziti-controller will attempt to parse the edge configuration. Removing this +# section, commenting out, or altering the name of the section will cause the edge to not run. +edge: + # This section represents the configuration of the Edge API that is served over HTTPS + api: + #(optional, default 90s) Alters how frequently heartbeat and last activity values are persisted + # activityUpdateInterval: 90s + #(optional, default 250) The number of API Sessions updated for last activity per transaction + # activityUpdateBatchSize: 250 + # sessionTimeout - optional, default 10m + # The number of minutes before an Edge API session will timeout. Timeouts are reset by + # API requests and connections that are maintained to Edge Routers + sessionTimeout: 30m + # address - required + # The default address (host:port) to use for enrollment for the Client API. This value must match one of the addresses + # defined in a bind point's address field for the `edge-client` API in the web section. + address: {{.Host.PublicIp}}:1280 + # enrollment - required + # A section containing settings pertaining to enrollment. + enrollment: + # signingCert - required + # A Ziti Identity configuration section that specifically makes use of the cert and key fields to define + # a signing certificate from the PKI that the Ziti environment is using to sign certificates. The signingCert.cert + # will be added to the /.well-known CA store that is used to bootstrap trust with the Ziti Controller. + signingCert: + cert: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/ctrl/certs/ctrl.cert + key: /home/{{ .Model.MustVariable "credentials.ssh.username" }}/fablab/pki/ctrl/keys/ctrl.key + + # edgeIdentity - optional + # A section for identity enrollment specific settings + edgeIdentity: + # duration - optional, default 5m + # The length of time that a Ziti Edge Identity enrollment should remain valid. After + # this duration, the enrollment will expire and not longer be usable. + duration: 5m + # edgeRouter - Optional + # A section for edge router enrollment specific settings. + edgeRouter: + # duration - optional, default 5m + # The length of time that a Ziti Edge Router enrollment should remain valid. After + # this duration, the enrollment will expire and not longer be usable. + duration: 5m + + +# web - optional +# Defines webListeners that will be hosted by the controller. Each webListener can host many APIs and be bound to many +# bind points. +web: + # name - required + # Provides a name for this listener, used for logging output. Not required to be unique, but is highly suggested. + - name: all-apis-localhost + # bindPoints - required + # One or more bind points are required. A bind point specifies an interface (interface:port string) that defines + # where on the host machine the webListener will listen and the address (host:port) that should be used to + # publicly address the webListener(i.e. mydomain.com, localhost, 127.0.0.1). This public address may be used for + # incoming address resolution as well as used in responses in the API. + bindPoints: + #interface - required + # A host:port string on which network interface to listen on. 0.0.0.0 will listen on all interfaces + - interface: 0.0.0.0:1280 + + # address - required + # The public address that external incoming requests will be able to resolve. Used in request processing and + # response content that requires full host:port/path addresses. + address: {{.Host.PublicIp}}:1280 + + # newAddress - optional + # A host:port string which will be sent out as an HTTP header "ziti-new-address" if specified. If the header + # is present, clients should update location configuration to immediately use the new address for future + # connections. The value of newAddress must be resolvable both via DNS and validate via certificates + #newAddress: localhost:1280 + # identity - optional + # Allows the webListener to have a specific identity instead of defaulting to the root `identity` section. + # identity: + # cert: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ctrl-client.cert.pem + # server_cert: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ctrl-server.cert.pem + # key: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/private/ctrl.key.pem + # ca: ${ZITI_SOURCE}/ziti/etc/ca/intermediate/certs/ca-chain.cert.pem + # options - optional + # Allows the specification of webListener level options - mainly dealing with HTTP/TLS settings. These options are + # used for all http servers started by the current webListener. + options: + # idleTimeout - optional, default 5000ms + # The maximum amount of idle time in milliseconds allowed for pipelined HTTP requests. Setting this too high + # can cause resources on the host to be consumed as clients remain connected and idle. Lowering this value + # will cause clients to reconnect on subsequent HTTPs requests. + idleTimeout: 5000ms #http timeouts, new + + # readTimeout - optional, default 5000ms + # The maximum amount of time in milliseconds http servers will wait to read the first incoming requests. A higher + # value risks consuming resources on the host with clients that are acting bad faith or suffering from high latency + # or packet loss. A lower value can risk losing connections to high latency/packet loss clients. + + readTimeout: 5000ms + # writeTimeout - optional, default 10000ms + # The total maximum time in milliseconds that the http server will wait for a single requests to be received and + # responded too. A higher value can allow long running requests to consume resources on the host. A lower value + # can risk ending requests before the server has a chance to respond. + + writeTimeout: 100000ms + # minTLSVersion - optional, default TSL1.2 + # The minimum version of TSL to support + + minTLSVersion: TLS1.2 + # maxTLSVersion - optional, default TSL1.3 + # The maximum version of TSL to support + + maxTLSVersion: TLS1.3 + # apis - required + # Allows one or more APIs to be bound to this webListener + apis: + # binding - required + # Specifies an API to bind to this webListener. Built-in APIs are + # - health-checks + # - edge-management + # - edge-client + # - fabric-management + - binding: health-checks + options: {} + - binding: fabric + - binding: edge-management + # options - variable optional/required + # This section is used to define values that are specified by the API they are associated with. + # These settings are per API. The example below is for the `edge-api` and contains both optional values and + # required values. + options: {} + - binding: edge-client + options: {} diff --git a/zititest/models/db-creation/configs/router.yml.tmpl b/zititest/models/db-creation/configs/router.yml.tmpl new file mode 100644 index 000000000..788799f78 --- /dev/null +++ b/zititest/models/db-creation/configs/router.yml.tmpl @@ -0,0 +1,70 @@ +{{$ssh_username := .Model.MustVariable "credentials.ssh.username"}} +{{$identity := .Component.Id}} +{{$ctrl_ip := publicIp "component#ctrl"}} +{{$router_ip := .Host.PublicIp}} + +v: 3 + +enableDebugOps: true + +identity: + cert: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}-client.cert + server_cert: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}-server.cert + key: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}.key + ca: /home/{{$ssh_username}}/fablab/cfg/{{$identity}}-server.chain.pem + +ctrl: + endpoint: tls:{{$ctrl_ip}}:6262 + +healthChecks: + ctrlPingCheck: + # How often to ping the controller over the control channel. Defaults to 30 seconds + interval: 30s + # When to timeout the ping. Defaults to 15 seconds + timeout: 15s + # How long to wait before pinging the controller. Defaults to 15 seconds + initialDelay: 15s + +metrics: + reportInterval: 15s + messageQueueSize: 10 + +link: + listeners: + - binding: transport + bind: tls:0.0.0.0:6000 + advertise: tls:{{$router_ip}}:6000 + dialers: + - binding: transport + +listeners: +{{if .Component.HasTag "tunneler"}} + - binding: tunnel + options: + mode: tproxy +{{end}} + - binding: edge + address: tls:0.0.0.0:6262 + options: + # (required) The public hostname and port combination that Ziti SDKs should connect on. Previously this was in the chanIngress section. + advertise: {{ .Host.PublicIp }}:6262 + +# By having an 'edge' section defined, the ziti-router will attempt to parse the edge configuration. Removing this +# section, commenting out, or altering the name of the section will cause the router to no longer operate as an Edge +# Router. +edge: + # (required) Information used to generate the initial registration CSR. For documentation on these fields please + # refer to the openssl documentation. These values MUST be supplied and have no defaults. + csr: + country: US + province: NC + locality: Charlotte + organization: NetFoundry + organizationalUnit: Ziti + + # (required) SANs that this Gateways certs should contain. At least one IP or DNS SAN should be defined that matches + # the edge listeners "advertise" value from the "listeners" section. + sans: + ip: + - {{ .Host.PublicIp }} + diff --git a/zititest/models/db-creation/configs/ziti.hcl b/zititest/models/db-creation/configs/ziti.hcl new file mode 100644 index 000000000..4af438cc0 --- /dev/null +++ b/zititest/models/db-creation/configs/ziti.hcl @@ -0,0 +1,9 @@ +service { + name = "ziti" + id = "ziti" + port = 6262 + meta { + build_number= "${build_number}" + ziti_version= "${ziti_version}" + } +} \ No newline at end of file diff --git a/zititest/models/db-creation/main.go b/zititest/models/db-creation/main.go new file mode 100644 index 000000000..10d8b4146 --- /dev/null +++ b/zititest/models/db-creation/main.go @@ -0,0 +1,129 @@ +package main + +import ( + "embed" + "github.com/openziti/fablab" + "github.com/openziti/fablab/kernel/lib/actions/component" + "github.com/openziti/fablab/kernel/lib/actions/host" + "github.com/openziti/fablab/kernel/lib/binding" + "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/aws_ssh_key" + semaphore_0 "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/semaphore" + terraform_0 "github.com/openziti/fablab/kernel/lib/runlevel/0_infrastructure/terraform" + distribution "github.com/openziti/fablab/kernel/lib/runlevel/3_distribution" + "github.com/openziti/fablab/kernel/lib/runlevel/3_distribution/rsync" + aws_ssh_key2 "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/aws_ssh_key" + "github.com/openziti/fablab/kernel/lib/runlevel/6_disposal/terraform" + "github.com/openziti/fablab/kernel/model" + "github.com/openziti/fablab/resources" + "github.com/openziti/ziti/zititest/models/db-creation/actions" + "github.com/openziti/ziti/zititest/models/test_resources" + "github.com/openziti/ziti/zititest/zitilab" + "github.com/openziti/ziti/zititest/zitilab/actions/edge" + "os" + "path" + "time" +) + +//go:embed configs +var configResource embed.FS + +// Definition of the model, which houses most you need to run things. +var m = &model.Model{ + Id: "db-creation", + Scope: model.Scope{ + Defaults: model.Variables{ + "environment": "db-creation", + "credentials": model.Variables{ + "ssh": model.Variables{ + "username": "ubuntu", + }, + "edge": model.Variables{ + "username": "admin", + "password": "admin", + }, + "aws": model.Variables{ + "managed_key": true, + }, + }, + }, + }, + + StructureFactories: []model.Factory{ + //model.NewScaleFactoryWithDefaultEntityFactory(scaleStrategy{}), + }, + + Factories: []model.Factory{ + //newStageFactory(), + }, + + Resources: model.Resources{ + resources.Configs: resources.SubFolder(configResource, "configs"), + resources.Binaries: os.DirFS(path.Join(os.Getenv("GOPATH"), "bin")), + resources.Terraform: test_resources.TerraformResources(), + }, + + Regions: model.Regions{ + "us-east-1": { + Region: "us-east-1", + Site: "us-east-1a", + Hosts: model.Hosts{ + "ctrl": { + InstanceType: "t3.micro", + Components: model.Components{ + "ctrl": { + Scope: model.Scope{Tags: model.Tags{"ctrl"}}, + Type: &zitilab.ControllerType{ + ConfigSourceFS: nil, + ConfigSource: "", + ConfigName: "", + Version: os.Getenv("ZITI_VERSION"), + LocalPath: "", + DNSNames: []string{actions.DomainName}, + }, + }, + }, + }, + }, + }, + }, + + Actions: model.ActionBinders{ + "bootstrap": actions.NewBootstrapAction(), + "stop": model.Bind(component.StopInParallel("ctrl", 1)), + "login": model.Bind(edge.Login("#ctrl")), + }, + + Infrastructure: model.Stages{ + aws_ssh_key.Express(), + terraform_0.Express(), + semaphore_0.Restart(90 * time.Second), + }, + + Distribution: model.Stages{ + distribution.DistributeSshKey("*"), + distribution.Locations("*", "logs"), + rsync.RsyncStaged(), + //rsync.NewRsyncHost("#ctrl", "resources/ctrl.db", "/home/ubuntu/fablab/ctrl.db"), + //rsync.NewRsyncHost("#ctrl", "resources/pki/", "/home/ubuntu/fablab/pki/"), + rsync.NewRsyncHost("#ctrl", "resources/aws_setup.sh", "/home/ubuntu/fablab/bin/aws_setup.sh"), + rsync.NewRsyncHost("#ctrl", "resources/db_creator_script_external.sh", "/home/ubuntu/fablab/bin/db_creator_script_external.sh"), + }, + + Disposal: model.Stages{ + model.StageActionF(func(run model.Run) error { + m := run.GetModel() + s := actions.Route53StringCreator(m, actions.Delete) + return host.Exec(m.MustSelectHost("#ctrl"), s).Execute(run) + }), + terraform.Dispose(), + aws_ssh_key2.Dispose(), + }, +} + +func main() { + m.AddActivationActions("stop", "bootstrap") + model.AddBootstrapExtension(binding.AwsCredentialsLoader) + model.AddBootstrapExtension(aws_ssh_key.KeyManager) + fablab.InitModel(m) + fablab.Run() +} diff --git a/zititest/models/db-creation/resources/aws_setup.sh b/zititest/models/db-creation/resources/aws_setup.sh new file mode 100644 index 000000000..c6a2f6bc9 --- /dev/null +++ b/zititest/models/db-creation/resources/aws_setup.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +if [ $# -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +AWS_ACCESS_KEY="$1" +AWS_SECRET_KEY="$2" + +export AWS_ACCESS_KEY_ID="$AWS_ACCESS_KEY" +export AWS_SECRET_ACCESS_KEY="$AWS_SECRET_KEY" + +aws configure set aws_access_key_id "${AWS_ACCESS_KEY_ID}" +aws configure set aws_secret_access_key "${AWS_SECRET_ACCESS_KEY}" +aws configure set default.region us-east-1 +aws configure set default.output json diff --git a/zititest/models/db-creation/resources/db_creator_script_external.sh b/zititest/models/db-creation/resources/db_creator_script_external.sh new file mode 100644 index 000000000..c210740fa --- /dev/null +++ b/zititest/models/db-creation/resources/db_creator_script_external.sh @@ -0,0 +1,149 @@ +#!/bin/bash + +exec >> bashlog.txt 2>&1 + +# Initial sleep to hopefully allow for pulling of ziti exe filename +sleep 10 + +# Set Sleep time easily for quick changes +sleep_time=.01625 + +# Set the directory path where ziti executable is +directory="/home/ubuntu/fablab/bin" + +# Set search string for 'ziti-' +search_string="ziti-" + +# Search for the file that contains the specified string +file=$(find "$directory" -type f -name "*$search_string*" -print -quit) + +# Check if a file was found +if [[ -n "$file" ]]; then + echo "File found: $file" + # Extract the file name from the full path and save it to a variable + filename=$(basename "$file") + echo "File name: $filename" +else + echo "File not found." +fi + +# cd to ziti bin dir +cd $directory || exit +ls -lsa + +# Get ziti_version +ziti_version=$(./${filename} -v) +echo "ziti_version: $ziti_version" +# Retrieve the instance metadata to get the public IP +public_ip=$(curl -s http://169.254.169.254/latest/meta-data/public-ipv4) +echo ${public_ip} + +# Login to ziti: +echo "Logging in to Ziti" +./ziti-${ziti_version} edge login ${public_ip}:1280 -y -u admin -p admin +echo "Ziti Edge Login Completed" + +# Add config variables for the intercept.v1 and host.v1 config types +json_response=$(./ziti-${ziti_version} edge list configs -j) +interceptv1=$(echo "$json_response" | jq -r '.data[0].id') +hostv1=$(echo "$json_response" | jq -r '.data[1].id') + +# Create some folder and bucket names + +BUCKET_NAME_IDENTITIES="fablab-ziti-identities" +FOLDER_NAME_IDENTITIES="identities-${ziti_version}" +BUCKET_NAME_PKI="fablab-ziti-pki" +FOLDER_NAME_PKI="pki-${ziti_version}" + +#Create folders with code version as suffix: +aws s3api put-object --bucket "$BUCKET_NAME_IDENTITIES" --key "$FOLDER_NAME_IDENTITIES"/ +aws s3api put-object --bucket "$BUCKET_NAME_PKI" --key "$FOLDER_NAME_PKI"/ + +#Copy the full pki directory into s3: +# aws s3 sync s3:/// +aws s3 sync /home/ubuntu/fablab/pki s3://$BUCKET_NAME_PKI/$FOLDER_NAME_PKI + +# Make directory to store identities +mkdir identities-${ziti_version}; chmod 0755 identities-${ziti_version} + +# Set the name of your S3 buckets and folder +BUCKET_NAME_DB="fablab-ziti-databases" + +# Set document path and s3 key of ziti-db +DOCUMENT_PATH_DB="/home/ubuntu/fablab/ctrl.db" +S3_KEY_DB="ctrl.db-${ziti_version}" + +for i in {20000..24000}; do + ./ziti-${ziti_version} edge create service service$i -c ${interceptv1},${hostv1} + ./ziti-${ziti_version} edge create service-policy service${i}Bind Bind --service-roles @service${i} --identity-roles '#iperf-server' + ./ziti-${ziti_version} edge create service-policy service${i}Dial Dial --service-roles @service${i} --identity-roles '#iperf-client' + ./ziti-${ziti_version} edge create serp service${i} --service-roles @service${i} --edge-router-roles '#all' + DOCUMENT_PATH_IDENTITIES="identities-${ziti_version}/identity${i}.json" + S3_KEY_IDENTITIES="identity${i}.json" + if ((i < 20100)); then + ./ziti-${ziti_version} edge create identity user identity${i} -o identities-${ziti_version}/identity${i}.jwt -a 'iperf.service.client.dial.100,iperf.service.client.dial.200,iperf.service.client.dial.300,iperf.service.client.dial.400,iperf.service.client.dial.500,iperf.service.client.dial.1000,iperf.service.client.dial.2000,iperf.service.client.dial.3000,iperf.service.client.dial.4000,iperf.service.client.dial.5000' + ./ziti-${ziti_version} edge enroll identities-${ziti_version}/identity${i}.jwt + aws s3 cp $DOCUMENT_PATH_IDENTITIES s3://$BUCKET_NAME_IDENTITIES/$FOLDER_NAME_IDENTITIES/$S3_KEY_IDENTITIES + sleep ${sleep_time} + elif ((20101 < i < 20200)); then + ./ziti-${ziti_version} edge create identity user identity${i} -o identities-${ziti_version}/identity${i}.jwt -a 'iperf.service.client.dial.200,iperf.service.client.dial.300,iperf.service.client.dial.400,iperf.service.client.dial.500,iperf.service.client.dial.1000,iperf.service.client.dial.2000,iperf.service.client.dial.3000,iperf.service.client.dial.4000,iperf.service.client.dial.5000' + ./ziti-${ziti_version} edge enroll identities-${ziti_version}/identity${i}.jwt + aws s3 cp $DOCUMENT_PATH_IDENTITIES s3://$BUCKET_NAME_IDENTITIES/$FOLDER_NAME_IDENTITIES/$S3_KEY_IDENTITIES + sleep ${sleep_time} + elif ((20201 < i < 20300)); then + ./ziti-${ziti_version} edge create identity user identity${i} -o identities-${ziti_version}/identity${i}.jwt -a 'iperf.service.client.dial.300,iperf.service.client.dial.400,iperf.service.client.dial.500,iperf.service.client.dial.1000,iperf.service.client.dial.2000,iperf.service.client.dial.3000,iperf.service.client.dial.4000,iperf.service.client.dial.5000' + ./ziti-${ziti_version} edge enroll identities-${ziti_version}/identity${i}.jwt + aws s3 cp $DOCUMENT_PATH_IDENTITIES s3://$BUCKET_NAME_IDENTITIES/$FOLDER_NAME_IDENTITIES/$S3_KEY_IDENTITIES + sleep ${sleep_time} + elif ((20301 < i < 20400)); then + ./ziti-${ziti_version} edge create identity user identity${i} -o identities-${ziti_version}/identity${i}.jwt -a 'iperf.service.client.dial.400,iperf.service.client.dial.500,iperf.service.client.dial.1000,iperf.service.client.dial.2000,iperf.service.client.dial.3000,iperf.service.client.dial.4000,iperf.service.client.dial.5000' + ./ziti-${ziti_version} edge enroll identities-${ziti_version}/identity${i}.jwt + aws s3 cp $DOCUMENT_PATH_IDENTITIES s3://$BUCKET_NAME_IDENTITIES/$FOLDER_NAME_IDENTITIES/$S3_KEY_IDENTITIES + sleep ${sleep_time} + elif ((20401 < i < 20500)); then + ./ziti-${ziti_version} edge create identity user identity${i} -o identities-${ziti_version}/identity${i}.jwt -a 'iperf.service.client.dial.500,iperf.service.client.dial.1000,iperf.service.client.dial.2000,iperf.service.client.dial.3000,iperf.service.client.dial.4000,iperf.service.client.dial.5000' + ./ziti-${ziti_version} edge enroll identities-${ziti_version}/identity${i}.jwt + aws s3 cp $DOCUMENT_PATH_IDENTITIES s3://$BUCKET_NAME_IDENTITIES/$FOLDER_NAME_IDENTITIES/$S3_KEY_IDENTITIES + sleep ${sleep_time} + elif ((20501