diff --git a/README.md b/README.md index c431a35dc1d..109750dd0bb 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,11 @@ and often rely on network ACLs and manual updating. * [ZMS Server](docs/setup_zms_prod.md) * [ZTS Server](docs/setup_zts_prod.md) * [UI Server](docs/setup_ui_prod.md) +* AWS Setup + * [Introduction](docs/aws_athenz_setup.md) + * [ZMS Server](docs/aws_zms_setup.md) + * [ZTS Server](docs/aws_zts_setup.md) + * [UI Server](docs/aws_ui_setup.md) * Architecture * [Data Model](docs/data_model.md) * [System View](docs/system_view.md) diff --git a/assembly/ui/pom.xml b/assembly/ui/pom.xml index d38bd0796fc..9fa4a05fcb7 100644 --- a/assembly/ui/pom.xml +++ b/assembly/ui/pom.xml @@ -58,6 +58,21 @@ + + package-ui-assembly-aws + package + + single + + + posix + ../../../athenz/aws-setup/ui-setup/tars/ + athenz-ui + + ui.xml + + + diff --git a/assembly/zms/pom.xml b/assembly/zms/pom.xml index f0430af1e2a..9b56219a727 100644 --- a/assembly/zms/pom.xml +++ b/assembly/zms/pom.xml @@ -72,6 +72,21 @@ + + package-zms-assembly-aws + package + + single + + + posix + ../../../athenz/aws-setup/zms-setup/tars/ + athenz-zms + + zms.xml + + + diff --git a/assembly/zts/pom.xml b/assembly/zts/pom.xml index b679c4ee00f..16e4de6b105 100644 --- a/assembly/zts/pom.xml +++ b/assembly/zts/pom.xml @@ -72,6 +72,21 @@ + + package-zts-assembly-aws + package + + single + + + posix + ../../../athenz/aws-setup/zts-setup/tars/ + athenz-zts + + zts.xml + + + diff --git a/aws-setup/athenz-conf-aws/Makefile b/aws-setup/athenz-conf-aws/Makefile new file mode 100755 index 00000000000..86a19d722ed --- /dev/null +++ b/aws-setup/athenz-conf-aws/Makefile @@ -0,0 +1,77 @@ +# +# Makefile to build Athenz Config file generation utility +# Prerequisite: Go development environment +# +# Copyright 2018 Oath, Inc. +# Licensed under the Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0 +# + +GOPKGNAME = github.com/yahoo/athenz/utils/athenz-conf-aws +PKG_DATE=$(shell date '+%Y-%m-%dT%H:%M:%S') +BINARY=athenz-conf-aws +SRC=athenz-conf-aws.go +FMT_LOG=/tmp/athenz-conf-aws-fmt.log +IMPORTS_LOG=/tmp/athenz-conf-aws-imports.log + +# check to see if go utility is installed +GO := $(shell command -v go 2> /dev/null) +export GOPATH=$(PWD) + +ifdef GO + +# we need to make sure we have go 1.7+ +# the output for the go version command is: +# go version go1.7.3 darwin/amd64 + +GO_VER_GTEQ7 := $(shell expr `go version | cut -f 3 -d' ' | cut -f2 -d.` \>= 7) +ifneq "$(GO_VER_GTEQ7)" "1" +all: + @echo "Please install 1.7.x or newer version of golang" +else + +.PHONY: source vet fmt imports linux darwin +all: source vet fmt imports linux darwin + +endif + +else + +all: + @echo "go is not available please install golang" + +endif + +# we need to build the athenz-conf with the local copy + +source: + @echo "Cleanup up local GOPATH src directory..." + rm -rf src + @echo "Setting up the source code..." + mkdir -p /tmp/athenz-conf-aws-build/src/$(GOPKGNAME) + cp -r * /tmp/athenz-conf-aws-build/src/$(GOPKGNAME)/. + mv /tmp/athenz-conf-aws-build/src . + @echo "Getting dependency packages..." + go get -t -d -tags testing $(GOPKGNAME)/... + +imports: + go get golang.org/x/tools/cmd/goimports + go list $(GOPKGNAME)/... | sed "s:^:$(GOPATH)/src/:" | xargs $(GOPATH)/bin/goimports -d >$(IMPORTS_LOG) + @if [ -s $(IMPORTS_LOG) ]; then echo goimports FAIL; cat $(IMPORTS_LOG); false; fi + +vet: + go vet $(GOPKGNAME)/... + +fmt: + go list $(GOPKGNAME)/... | sed "s:^:$(GOPATH)/src/:" | xargs gofmt -d >$(FMT_LOG) + @if [ -s $(FMT_LOG) ]; then echo gofmt FAIL; cat $(FMT_LOG); false; fi + +darwin: + @echo "Building darwin client..." + GOOS=darwin go build -ldflags "-X main.VERSION=$(PKG_VERSION) -X main.BUILD_DATE=$(PKG_DATE)" -o target/darwin/$(BINARY) $(SRC) + +linux: + @echo "Building linux client..." + GOOS=linux go build -ldflags "-X main.VERSION=$(PKG_VERSION) -X main.BUILD_DATE=$(PKG_DATE)" -o target/linux/$(BINARY) $(SRC) + +clean: + rm -rf target src bin pkg /tmp/athenz-conf-aws-build $(FMT_LOG) $(IMPORTS_LOG) diff --git a/aws-setup/athenz-conf-aws/athenz-conf-aws.go b/aws-setup/athenz-conf-aws/athenz-conf-aws.go new file mode 100755 index 00000000000..c644e5341d7 --- /dev/null +++ b/aws-setup/athenz-conf-aws/athenz-conf-aws.go @@ -0,0 +1,94 @@ +package main + +import ( + "bytes" + "flag" + "fmt" + "log" + "io/ioutil" + "os" + + "github.com/yahoo/athenz/libs/go/zmssvctoken" +) + +func usage() string { + var buf bytes.Buffer + buf.WriteString("usage: athenz-conf-aws -z -k [flags]\n") + buf.WriteString(" flags:\n") + buf.WriteString(" -z zms_url Base URL of the ZMS server to use\n") + buf.WriteString(" -k zms_public key Public key of ZMS server to use\n" ) + buf.WriteString(" -t zts_url Base URL of the ZTS server to use\n") + buf.WriteString(" -e zts_public key Public key of zms server to use\n" ) + buf.WriteString(" -o output_file Output config filename (default=/opt/zts/conf/athenz.conf)\n" ) + buf.WriteString("\n") + return buf.String() +} + +func main() { + + var ztsUrl, zmsUrl, ztsPublicKey, zmsPublicKey , outputFile string + flag.StringVar(&zmsUrl,"z", "", "Base URL of the ZMS server to use") + flag.StringVar(&ztsUrl, "t", "", "Base URL of the ZTS server to use") + flag.StringVar(&zmsPublicKey, "k", "", "Public key file of ZMS server to use") + flag.StringVar(&ztsPublicKey, "e", "", "Public key file of ZTS server to use") + flag.StringVar(&outputFile, "o", "/opt/zts/conf/athenz.conf", "The output athenz conf file") + flag.Usage = func() { + fmt.Println(usage()) + } + + flag.Parse() + + if zmsUrl == "" || zmsPublicKey == "" { + fmt.Println(usage()) + log.Fatalf("zms url and key flags are mandatory") + } + + if (ztsUrl == "" && ztsPublicKey != "" )|| (ztsUrl != "" && ztsPublicKey == ""){ + fmt.Println(usage()) + log.Fatalf("Both zts url and key should be passed") + } + + byte, err := ioutil.ReadFile(zmsPublicKey) + if err != nil { + log.Fatalln(err) + } + zmsKey := new(zmssvctoken.YBase64).EncodeToString(byte) + + var ztsKey string + if ztsPublicKey != ""{ + byte, err = ioutil.ReadFile(ztsPublicKey) + if err != nil { + log.Fatalln(err) + } + ztsKey = new(zmssvctoken.YBase64).EncodeToString(byte) + } + + + var buf bytes.Buffer + buf.WriteString("{\n") + buf.WriteString("\"zmsUrl\": \"" + zmsUrl + "\",\n") + buf.WriteString("\"ztsUrl\": \"" + ztsUrl + "\",\n") + buf.WriteString("\"ztsPublicKeys\": [\n") + buf.WriteString(" {\n") + buf.WriteString(" \"id\": \"0\",\n") + buf.WriteString(" \"key\": \"" + ztsKey + "\"\n") + buf.WriteString(" }") + buf.WriteString("\n") + buf.WriteString("], \n") + buf.WriteString("\"zmsPublicKeys\": [\n") + buf.WriteString(" {\n") + buf.WriteString(" \"id\": \"0\",\n") + buf.WriteString(" \"key\": \"" + zmsKey + "\"\n") + buf.WriteString(" }") + buf.WriteString("\n") + buf.WriteString("]") + buf.WriteString("\n") + buf.WriteString("}\n") + + err = ioutil.WriteFile(outputFile, buf.Bytes(), 0644) + if err != nil { + log.Fatalf("Unable to write athenz.conf file, err: %v", err) + } + os.Exit(0) + +} \ No newline at end of file diff --git a/aws-setup/athenz-conf-aws/pom.xml b/aws-setup/athenz-conf-aws/pom.xml new file mode 100755 index 00000000000..b5e451332cf --- /dev/null +++ b/aws-setup/athenz-conf-aws/pom.xml @@ -0,0 +1,71 @@ + + + + 4.0.0 + + + com.yahoo.athenz + athenz + 1.7.52-SNAPSHOT + ../../pom.xml + + + athenz-conf-aws + jar + athenz-conf-aws + Athenz Config File Utility + + + true + true + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.1.1 + + + + exec + + compile + + + + make + + PKG_VERSION=${project.parent.version} + clean + all + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + default-jar + + + + + + + + diff --git a/aws-setup/cloud-formation/packer_vpc.yaml b/aws-setup/cloud-formation/packer_vpc.yaml new file mode 100755 index 00000000000..1001a649a2d --- /dev/null +++ b/aws-setup/cloud-formation/packer_vpc.yaml @@ -0,0 +1,316 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: 'Athenz packer standard 2 Availabilty zone configuration template' +Parameters: + packerVPCCidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the VPC. + Default: "10.0.0.0/24" + PrivateSubnet01CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the VPC. + Default: "10.0.0.0/26" + PublicSubnet01CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the VPC. + Default: "10.0.0.64/26" + Environment: + Type: String + Description: The environment packer is running in + AllowedValues: + - prod + - stage + - dev +Resources: + packerVPC: + Type: 'AWS::EC2::VPC' + Properties: + CidrBlock: !Ref 'packerVPCCidrBlock' + EnableDnsSupport: true + EnableDnsHostnames: true + Tags: + - Key: Name + Value: !Sub ${Environment}-packer + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet01: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PrivateSubnet01CidrBlock' + VpcId: !Ref 'packerVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-packer-${AWS::Region}-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet01: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PublicSubnet01CidrBlock' + VpcId: !Ref 'packerVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-packer-${AWS::Region}-public + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + Nacl: + Type: "AWS::EC2::NetworkAcl" + Properties: + VpcId: !Ref 'packerVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-packer + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + NetworkAclEntry01: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '100' + Protocol: "6" + RuleAction: allow + CidrBlock: !Ref 'packerVPCCidrBlock' + PortRange: + From: '22' + To: '22' + NetworkAclEntry02: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '110' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '8443' + To: '8443' + NetworkAclEntry03: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '120' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '80' + To: '80' + NetworkAclEntry04: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '130' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '443' + To: '443' + NetworkAclEntry05: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '140' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '1024' + To: '65535' + NetworkAclEntry06: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '150' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '8080' + To: '8080' + NetworkAclEntry07: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '100' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '22' + To: '22' + NetworkAclEntry08: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '110' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '8443' + To: '8443' + NetworkAclEntry09: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '120' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '80' + To: '80' + NetworkAclEntry10: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '130' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '443' + To: '443' + NetworkAclEntry11: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '140' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '1024' + To: '65535' + NetworkAclEntry12: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '150' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '8080' + To: '8080' + PrivateSubnet01Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PrivateSubnet01' + NetworkAclId: !Ref 'Nacl' + PublicSubnet01Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PublicSubnet01' + NetworkAclId: !Ref 'Nacl' + InternetGateway: + Type: "AWS::EC2::InternetGateway" + Properties: + Tags: + - Key: Name + Value: !Sub ${Environment}-packer + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + VPCGatewayAttachment: + Type: "AWS::EC2::VPCGatewayAttachment" + Properties: + InternetGatewayId: !Ref 'InternetGateway' + VpcId: !Ref 'packerVPC' + PublicSubnet01NatGateway: + Type: "AWS::EC2::NatGateway" + Properties: + AllocationId: !GetAtt PublicSubnet01EIP.AllocationId + SubnetId: !Ref 'PublicSubnet01' + Tags: + - Key: Name + Value: !Sub ${Environment}-packer-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet01EIP: + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + PublicSubnetRouteTable: + Type: "AWS::EC2::RouteTable" + Properties: + VpcId: !Ref 'packerVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-packer-${AWS::Region}-public + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + GatewayRoute: + Type: "AWS::EC2::Route" + Properties: + DestinationCidrBlock: '0.0.0.0/0' + GatewayId: !Ref 'InternetGateway' + RouteTableId: !Ref 'PublicSubnetRouteTable' + DependsOn: VPCGatewayAttachment + PrivateSubnet01RouteTable: + Type: "AWS::EC2::RouteTable" + Properties: + VpcId: !Ref 'packerVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-packer-${AWS::Region}-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet01Route: + Type: "AWS::EC2::Route" + Properties: + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'PublicSubnet01NatGateway' + RouteTableId: !Ref 'PrivateSubnet01RouteTable' + PublicSubnet01RouteTableAssociaton: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PublicSubnetRouteTable' + SubnetId: !Ref 'PublicSubnet01' + PrivateSubnet01RouteTableAssociation: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PrivateSubnet01RouteTable' + SubnetId: !Ref 'PrivateSubnet01' \ No newline at end of file diff --git a/aws-setup/ui-setup/build/bin/athenz_conf.sh b/aws-setup/ui-setup/build/bin/athenz_conf.sh new file mode 100755 index 00000000000..40076927991 --- /dev/null +++ b/aws-setup/ui-setup/build/bin/athenz_conf.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +############# +# Usage: athenz_conf.sh [outputFile] [zts key bucket path] [zts url] [zms key bucket path] [zms url] +# Generates Athenz conf file +############### + +displayUsage() { + echo "athenz_conf.sh [outputFile] [uiDataBucketName][zmsUrl]"; + echo 'athenz_conf.sh ./output.json athenz-zts-data-us-west-2 https://zms.athenz.com:4443/'; +} + +if [ $# -ne 3 ] +then + displayUsage + exit 1 +fi + +zms_public_key_file=zms_service_x509_key_public.pem + + +outputFile=$1 +dataBucketName=$2 +zmsUrl=$3 + +# download CA certs from S3 bucket and store locally in temp directory +aws s3 cp s3://$dataBucketName/$zms_public_key_file /tmp/zms_pub_key + +sudo /opt/athenz-ui/bin/linux/athenz-conf-aws -z $zmsUrl -k /tmp/zms_pub_key -o $outputFile diff --git a/aws-setup/ui-setup/build/bin/aws_config.sh b/aws-setup/ui-setup/build/bin/aws_config.sh new file mode 100755 index 00000000000..0ab33023c9a --- /dev/null +++ b/aws-setup/ui-setup/build/bin/aws_config.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +aws_config_dir="$HOME/.aws" + +if [ -z "$HOME" ]; then + aws_config_dir="/athenz-zts/.aws" +fi + +echo "Configuring aws config in $aws_config_dir" + +if [ ! -d "$aws_config_dir" ]; then + mkdir $aws_config_dir +fi + +aws_config="[default]\nregion=$REGION" +echo -e $aws_config > $aws_config_dir/config diff --git a/aws-setup/ui-setup/build/bin/get_certs.sh b/aws-setup/ui-setup/build/bin/get_certs.sh new file mode 100755 index 00000000000..922f3720a8b --- /dev/null +++ b/aws-setup/ui-setup/build/bin/get_certs.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +# download server cert and key from private s3 bucket +# aws s3 client will automatically decrypt the data + +BUCKET_NAME=$1 +KEY_FILE=service_x509_key +CERT_FILE=service_x509_cert +SERVICE_PRIVATE_KEY_FILE=service_private_key +ZMS_CA_CERT_FILE=zms_service_x509_ca_certs + +sudo mkdir -p /opt/athenz-ui/keys +aws s3 cp s3://$BUCKET_NAME/$KEY_FILE /opt/athenz-ui/keys/ui_key.pem +aws s3 cp s3://$BUCKET_NAME/$CERT_FILE /opt/athenz-ui/keys/ui_cert.pem +aws s3 cp s3://$BUCKET_NAME/$SERVICE_PRIVATE_KEY_FILE /opt/athenz-ui/keys/athenz.ui.pem +openssl rsa -in /opt/athenz-ui/keys/athenz.ui.pem -pubout > /opt/athenz-ui/keys/athenz.ui_pub.pem +aws s3 cp s3://$BUCKET_NAME/$ZMS_CA_CERT_FILE /opt/athenz-ui/keys/zms_cert.pem \ No newline at end of file diff --git a/aws-setup/ui-setup/build/bin/ui.sh b/aws-setup/ui-setup/build/bin/ui.sh new file mode 100755 index 00000000000..1cd6b7355ee --- /dev/null +++ b/aws-setup/ui-setup/build/bin/ui.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -e + +echo "========= Getting region and env from AWS =========" + +REGION=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone | sed 's/.$//') +ENV="dev" +BUCKET_NAME=test-athenz-ui-data-bucket +ATHENZ_CONF_PATH=/opt/athenz-ui/conf/athenz.conf + +export ENVIRONMENT="${ENV}" +export REGION="${REGION}" +export UI_SERVER="test.ui.athens.aws.oath.cloud" +export ZMS_SERVER="test.athens.aws.oath.cloud" +export ZMS_SERVER_URL="https://${ZMS_SERVER}:4443/zms/v1/" +export ROOT=/opt + +echo "initializing aws cloudwatch log setup" +sudo python /opt/athenz-ui/logs/awslogs-agent-setup.py -n -r $REGION -c /opt/athenz-ui/conf/awslogs.conf + +echo "generating athenz conf" +/opt/athenz-ui/bin/athenz_conf.sh $ATHENZ_CONF_PATH $BUCKET_NAME $ZMS_SERVER + +echo "Downloading certs and keys from s3 bucket" +/opt/athenz-ui/bin/get_certs.sh $BUCKET_NAME + +echo "Starting UI Server" +/bin/node /opt/athenz-ui/server.js +echo "UI server running at 443" \ No newline at end of file diff --git a/aws-setup/ui-setup/build/conf/awslogs.conf b/aws-setup/ui-setup/build/conf/awslogs.conf new file mode 100755 index 00000000000..9abc27b54a5 --- /dev/null +++ b/aws-setup/ui-setup/build/conf/awslogs.conf @@ -0,0 +1,8 @@ +[general] +state_file = /var/awslogs/state/agent-state + +[syslog] +file = /var/log/messages +log_group_name = athenz-ui-service +log_stream_name = {instance_id} +datetime_format = %b %d %H:%M:%S \ No newline at end of file diff --git a/aws-setup/ui-setup/build/conf/ui-user b/aws-setup/ui-setup/build/conf/ui-user new file mode 100755 index 00000000000..6cdff8f4320 --- /dev/null +++ b/aws-setup/ui-setup/build/conf/ui-user @@ -0,0 +1 @@ +athenz-ui ALL=(ALL) NOPASSWD: ALL \ No newline at end of file diff --git a/aws-setup/ui-setup/build/service/ui.service b/aws-setup/ui-setup/build/service/ui.service new file mode 100755 index 00000000000..fd2e6e52625 --- /dev/null +++ b/aws-setup/ui-setup/build/service/ui.service @@ -0,0 +1,15 @@ +[Unit] +Description=Athens UI +Wants=network-online.target ntpd.service +After=network-online.target + +[Service] +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=athenz-ui +Restart=on-failure +RestartSec=20 +ExecStart=/opt/athenz-ui/bin/ui.sh + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/aws-setup/ui-setup/cloud-formation/athens-ui-aws-instance-deployment.yaml b/aws-setup/ui-setup/cloud-formation/athens-ui-aws-instance-deployment.yaml new file mode 100755 index 00000000000..e6aa53c6b00 --- /dev/null +++ b/aws-setup/ui-setup/cloud-formation/athens-ui-aws-instance-deployment.yaml @@ -0,0 +1,127 @@ +Description: 'Athenz UI standard 2 Availabilty zone instance deployment template' +Parameters: + ServiceRole: + Type: String + Description: The UI Service IAM Role Name + Default: "athenz.ui-service" + KeyName: + Type: String + Description: The EC2 key pair for the instance + ServiceName: + Type: String + Description: The service name for UI server + Default: "ui" + ResourceStackName: + Type: String + Description: Name of Stack used to create AWS Resources + Environment: + Type: String + Description: The environment UI is running in + AllowedValues: + - prod + - stage + - dev + ImageId: + Type: AWS::EC2::Image::Id + Description: "The ImageId to use for the EC2 instance. Should be a format like ami-XXXXXXXX" + AutoScalingMinSize: + Type: String + Description: The minimum instances for auto scaling + Default: "2" + AutoScalingMaxSize: + Type: String + Description: The maximum instances for auto scaling + Default: "4" + AutoScalingDesiredCapacity: + Type: String + Description: The desired number of instances + Default: "2" + EbsOptimized: + Type: String + Description: If EBS is to be optimized + AllowedValues: + - "true" + - "false" + Default: "false" + Ec2InstanceType: + Type: String + Description: The instance type to use for the host + Default: t2.large + AllowedValues: + - t2.nano + - t2.micro + - t2.small + - t2.medium + - t2.large + - t2.xlarge + - t2.2xlarge + - m4.large + - m4.xlarge + - m4.2xlarge + - m4.4xlarge + - m4.10xlarge + - m4.16xlarge + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + - m5.12xlarge + - m5.24xlarge + - m5d.large + - m5d.xlarge + - m5d.2xlarge + - m5d.4xlarge + - m5d.12xlarge + - m5d.24xlarge + EbsVolumeType: + Type: String + Description: The value for EBS Volume type in Block Device Mappings for Launch Configuration + Default: "gp2" + EbsVolumeSize: + Type: Number + Description: The value for EBS Volume size Block Device Mappings for Launch Configuration + Default: "50" +Resources: + UIEC2AutoScalingGroup: + Type: 'AWS::AutoScaling::AutoScalingGroup' + Properties: + LaunchConfigurationName: !Ref UILaunchConfig + LoadBalancerNames: + - Fn::ImportValue: !Sub "${ResourceStackName}-LoadBalancerName" + MaxSize: !Ref AutoScalingMaxSize + MinSize: !Ref AutoScalingMinSize + Cooldown: 300 + VPCZoneIdentifier: + - Fn::ImportValue: !Sub "${ResourceStackName}-PrivateSubnet01ID" + - Fn::ImportValue: !Sub "${ResourceStackName}-PrivateSubnet02ID" + DesiredCapacity: !Ref AutoScalingDesiredCapacity + HealthCheckGracePeriod: 900 + HealthCheckType: ELB + Tags: + - Key: Name + Value: !Sub ${Environment}-asg-${ServiceName}-${AWS::Region} + PropagateAtLaunch: true + - Key: Environment + Value: !Ref Environment + PropagateAtLaunch: true + - Key: Stack + Value: !Ref AWS::StackName + PropagateAtLaunch: true + UILaunchConfig: + Type: 'AWS::AutoScaling::LaunchConfiguration' + Properties: + AssociatePublicIpAddress: false + IamInstanceProfile: !Sub arn:aws:iam::${AWS::AccountId}:instance-profile/${ServiceRole} + ImageId: !Ref ImageId + KeyName: !Ref KeyName + InstanceType: !Ref Ec2InstanceType + EbsOptimized: !Ref EbsOptimized + SecurityGroups: + - Fn::ImportValue: !Sub "${ResourceStackName}-ServerSecurityGroupID" + BlockDeviceMappings: + - DeviceName: "/dev/sda1" + Ebs: + VolumeSize: !Ref EbsVolumeSize + VolumeType: !Ref EbsVolumeType + DeleteOnTermination: true + InstanceMonitoring: true \ No newline at end of file diff --git a/aws-setup/ui-setup/cloud-formation/athens-ui-aws-resource-setup.yaml b/aws-setup/ui-setup/cloud-formation/athens-ui-aws-resource-setup.yaml new file mode 100755 index 00000000000..b730594e239 --- /dev/null +++ b/aws-setup/ui-setup/cloud-formation/athens-ui-aws-resource-setup.yaml @@ -0,0 +1,555 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: 'Athenz UI standard 2 Availabilty zone configuration template' +Parameters: + UIServiceName: + Type: String + Description: The service name for UI server + Default: "ui" + UIVPCCidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the UI VPC. + Default: "10.0.0.0/20" + PrivateSubnet01CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Private subnet Zone 1. + Default: "10.0.0.0/22" + PrivateSubnet02CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Private subnet Zone 2. + Default: "10.0.4.0/22" + PublicSubnet01CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for Public subnet Zone 1. + Default: "10.0.8.0/22" + PublicSubnet02CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for Public subnet Zone 2. + Default: "10.0.12.0/22" + GroupName: + Type: String + Description: The Athens domain for the account + Default: "Athenz" + Environment: + Type: String + Description: The environment UI is running in + AllowedValues: + - prod + - stage + - dev + S3AccessLogBucketName: + Type: String + Description: S3 bucket name to store access logs + Route53HostedZoneName: + Type: String + Description: The hosted zone name to place a CNAME entry for. Must end with a period. Empty string means do not create one. + Route53RecordName: + Type: String + Description: The hosted records to be added +Conditions: + CreateDNSRecordSet: !Not [!Equals [ !Ref Route53HostedZoneName, '']] + + +Resources: + UIVPC: + Type: 'AWS::EC2::VPC' + Properties: + CidrBlock: !Ref 'UIVPCCidrBlock' + EnableDnsSupport: true + EnableDnsHostnames: true + Tags: + - Key: Name + Value: !Sub ${Environment}-${UIServiceName} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet01: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PrivateSubnet01CidrBlock' + VpcId: !Ref 'UIVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${UIServiceName}-${AWS::Region}a-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet02: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 1 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PrivateSubnet02CidrBlock' + VpcId: !Ref 'UIVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${UIServiceName}-${AWS::Region}b-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet01: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PublicSubnet01CidrBlock' + VpcId: !Ref 'UIVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${UIServiceName}-${AWS::Region}a-public + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet02: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 1 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PublicSubnet02CidrBlock' + VpcId: !Ref 'UIVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${UIServiceName}-${AWS::Region}b-public + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + Nacl: + Type: "AWS::EC2::NetworkAcl" + Properties: + VpcId: !Ref 'UIVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${UIServiceName} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + NetworkAclEntry01: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '100' + Protocol: "6" + RuleAction: allow + CidrBlock: !Ref 'UIVPCCidrBlock' + PortRange: + From: '22' + To: '22' + NetworkAclEntry02: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '110' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '2222' + To: '2222' + NetworkAclEntry03: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '120' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '80' + To: '80' + NetworkAclEntry04: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '130' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '443' + To: '443' + NetworkAclEntry05: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '140' + Protocol: "17" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '123' + To: '123' + NetworkAclEntry06: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '200' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '1024' + To: '65535' + NetworkAclEntry07: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '100' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '22' + To: '22' + NetworkAclEntry08: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '110' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '2222' + To: '2222' + NetworkAclEntry09: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '120' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '80' + To: '80' + NetworkAclEntry10: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '130' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '443' + To: '443' + NetworkAclEntry11: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '140' + Protocol: "17" + RuleAction: allow + CidrBlock: !Ref 'UIVPCCidrBlock' + PortRange: + From: '123' + To: '123' + NetworkAclEntry12: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '200' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '1024' + To: '65535' + PrivateSubnet01Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PrivateSubnet01' + NetworkAclId: !Ref 'Nacl' + PrivateSubnet02Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PrivateSubnet02' + NetworkAclId: !Ref 'Nacl' + PublicSubnet01Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PublicSubnet01' + NetworkAclId: !Ref 'Nacl' + PublicSubnet02Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PublicSubnet02' + NetworkAclId: !Ref 'Nacl' + InternetGateway: + Type: "AWS::EC2::InternetGateway" + Properties: + Tags: + - Key: Name + Value: !Sub ${Environment}-${UIServiceName} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + VPCGatewayAttachment: + Type: "AWS::EC2::VPCGatewayAttachment" + Properties: + InternetGatewayId: !Ref 'InternetGateway' + VpcId: !Ref 'UIVPC' + PublicSubnet01NatGateway: + Type: "AWS::EC2::NatGateway" + Properties: + AllocationId: !GetAtt PublicSubnet01EIP.AllocationId + SubnetId: !Ref 'PublicSubnet01' + Tags: + - Key: Name + Value: !Sub ${Environment}-${UIServiceName}-${AWS::Region}a + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet01EIP: + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + PublicSubnet02NatGateway: + Type: "AWS::EC2::NatGateway" + Properties: + AllocationId: !GetAtt PublicSubnet02EIP.AllocationId + SubnetId: !Ref 'PublicSubnet02' + Tags: + - Key: Name + Value: !Sub ${Environment}-${UIServiceName}-${AWS::Region}b + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet02EIP: + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + PublicSubnetRouteTable: + Type: "AWS::EC2::RouteTable" + Properties: + VpcId: !Ref 'UIVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${UIServiceName}-${AWS::Region}-public + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + GatewayRoute: + Type: "AWS::EC2::Route" + Properties: + DestinationCidrBlock: '0.0.0.0/0' + GatewayId: !Ref 'InternetGateway' + RouteTableId: !Ref 'PublicSubnetRouteTable' + DependsOn: VPCGatewayAttachment + PrivateSubnet01RouteTable: + Type: "AWS::EC2::RouteTable" + Properties: + VpcId: !Ref 'UIVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${UIServiceName}-${AWS::Region}a-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet01Route: + Type: "AWS::EC2::Route" + Properties: + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'PublicSubnet01NatGateway' + RouteTableId: !Ref 'PrivateSubnet01RouteTable' + PrivateSubnet02RouteTable: + Type: "AWS::EC2::RouteTable" + Properties: + VpcId: !Ref 'UIVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${UIServiceName}-${AWS::Region}b-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet02Route: + Type: "AWS::EC2::Route" + Properties: + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'PublicSubnet02NatGateway' + RouteTableId: !Ref 'PrivateSubnet02RouteTable' + DependsOn: VPCGatewayAttachment + PublicSubnet01RouteTableAssociaton: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PublicSubnetRouteTable' + SubnetId: !Ref 'PublicSubnet01' + PublicSubnet02RouteTableAssociaton: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PublicSubnetRouteTable' + SubnetId: !Ref 'PublicSubnet02' + PrivateSubnet01RouteTableAssociation: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PrivateSubnet01RouteTable' + SubnetId: !Ref 'PrivateSubnet01' + PrivateSubnet02RouteTableAssociation: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PrivateSubnet02RouteTable' + SubnetId: !Ref 'PrivateSubnet02' + UIELBSecurityGroup: + Type: "AWS::EC2::SecurityGroup" + Properties: + GroupName: !Sub ${GroupName}-${Environment}-elb-sg-${UIServiceName}-${AWS::Region} + GroupDescription: 'UI public elb security group' + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: '443' + ToPort: '443' + CidrIp: '0.0.0.0/0' + VpcId: !Ref 'UIVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-elb-${UIServiceName}-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + UIServerSecurityGroup: + Type: "AWS::EC2::SecurityGroup" + Properties: + GroupName: !Sub ${GroupName}-${Environment}-server-sg-${UIServiceName}-${AWS::Region} + GroupDescription: 'UI public server security group' + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: '443' + ToPort: '443' + CidrIp: '0.0.0.0/0' + - IpProtocol: tcp + FromPort: '8443' + ToPort: '8443' + CidrIp: !Ref 'UIVPCCidrBlock' + VpcId: !Ref 'UIVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-server-${UIServiceName}-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + UILoadBalancer: + Type: "AWS::ElasticLoadBalancing::LoadBalancer" + Properties: + HealthCheck: + HealthyThreshold: 2 + Interval: 5 + Target: TCP:443 + Timeout: 2 + UnhealthyThreshold: 4 + Listeners: + - InstancePort: 443 + InstanceProtocol: TCP + LoadBalancerPort: 443 + Protocol: TCP + LoadBalancerName: !Sub ${Environment}-elb-${UIServiceName}-${AWS::Region} + Scheme: 'internet-facing' + ConnectionDrainingPolicy: + Enabled: 'true' + Timeout: '60' + CrossZone: true + SecurityGroups: + - !Ref UIELBSecurityGroup + Subnets: + - !Ref 'PublicSubnet01' + - !Ref 'PublicSubnet02' + AccessLoggingPolicy: + S3BucketName: !Ref S3AccessLogBucketName + S3BucketPrefix: !Sub elb-${UIServiceName} + Enabled: 'true' + EmitInterval: '5' + Tags: + - Key: Name + Value: !Sub ${Environment}-elb-UI-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + UIRecordSet: + Type: AWS::Route53::RecordSet + Condition: CreateDNSRecordSet + Properties: + Comment: CNAME record for the UI Server. + HostedZoneName: !Ref Route53HostedZoneName + Name: !Ref Route53RecordName + TTL: 60 + Type: CNAME + ResourceRecords: + - !GetAtt UILoadBalancer.DNSName +Outputs: + UIVPCID: + Description: The ID of the UI VPC + Value: !Ref UIVPC + Export: + Name: !Sub "${AWS::StackName}-VPCID" + PrivateSubnet01ID: + Description: TThe ID of Private Subnet Availability Zone 1 in UI VPC + Value: !Ref PrivateSubnet01 + Export: + Name: !Sub "${AWS::StackName}-PrivateSubnet01ID" + PrivateSubnet02ID: + Description: The ID of Private Subnet Availability Zone 2 in UI VPC + Value: !Ref PrivateSubnet02 + Export: + Name: !Sub "${AWS::StackName}-PrivateSubnet02ID" + LoadBalancerName : + Description: The name of UI Load Balancer + Value: !Ref UILoadBalancer + Export: + Name: !Sub "${AWS::StackName}-LoadBalancerName" + ServerSecurityGroupID: + Description: TThe ID of UI Server security group + Value: !Ref UIServerSecurityGroup + Export: + Name: !Sub "${AWS::StackName}-ServerSecurityGroupID" + diff --git a/aws-setup/ui-setup/cloud-formation/athens-ui-aws-roles-setup.yaml b/aws-setup/ui-setup/cloud-formation/athens-ui-aws-roles-setup.yaml new file mode 100755 index 00000000000..201a8f1f01c --- /dev/null +++ b/aws-setup/ui-setup/cloud-formation/athens-ui-aws-roles-setup.yaml @@ -0,0 +1,46 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: Roles needed for athens ui setup +Parameters: + AthensServiceRole: + Type: String + Description: The Athens role name for the service + Default: athenz.ui-service +Resources: + AthensServiceEC2Role: + Type: "AWS::IAM::Role" + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - + Effect: "Allow" + Principal: + Service: + - "ec2.amazonaws.com" + Action: + - "sts:AssumeRole" + Policies: + - + PolicyName: !Sub ${AthensServiceRole}.policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + - logs:DescribeLogStreams + - logs:DescribeLogGroups + Resource: "arn:aws:logs:*:*:*" + - Effect: "Allow" + Action: "ec2:DescribeTags" + Resource: "*" + Path: / + RoleName: !Ref AthensServiceRole + AthensEc2InstanceProfile: + Type: "AWS::IAM::InstanceProfile" + Properties: + Roles: + - !Ref AthensServiceEC2Role + InstanceProfileName: !Ref AthensServiceRole \ No newline at end of file diff --git a/aws-setup/ui-setup/packer/aws/packer.json b/aws-setup/ui-setup/packer/aws/packer.json new file mode 100755 index 00000000000..da3f02fa80d --- /dev/null +++ b/aws-setup/ui-setup/packer/aws/packer.json @@ -0,0 +1,99 @@ +{ + "variables": { + "subnet_id":"subnet-xxxxxxxx", + "vpc_id": "vpc-xxxxxxxxxxxxx", + "aws_region": "{{env `AWS_REGION`}}", + "aws_ami_name": "ui-aws-cd-image", + "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}", + "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}", + "aws_session_token": "{{env `AWS_SESSION_TOKEN`}}", + "ssh_keypair_name":"keypair-name", + "ssh_private_key_file":"path to ssh key file", + "source_ami": "ami-02c71d7a" + }, + "builders": [ + { + "access_key": "{{user `aws_access_key`}}", + "secret_key": "{{user `aws_secret_key`}}", + "token": "{{user `aws_session_token`}}", + "name": "amazon-ebs", + "ssh_username": "centos", + "ssh_keypair_name":"{{user `ssh_keypair_name`}}", + "ssh_private_key_file":"{{user `ssh_private_key_file`}}", + "type": "amazon-ebs", + "region": "{{user `aws_region`}}", + "source_ami": "{{user `source_ami`}}", + "ami_block_device_mappings": [ + { + "device_name": "/dev/sda1", + "volume_type": "gp2", + "volume_size": 50, + "encrypted": true, + "delete_on_termination": true + } + ], + "encrypt_boot": true, + "instance_type": "t2.micro", + "ami_name": "{{user `aws_ami_name`}}", + "ami_description": "UI Image for cloud formation", + "associate_public_ip_address": "true", + "subnet_id": "{{ user `subnet_id` }}", + "vpc_id": "{{ user `vpc_id` }}" + }], + + "provisioners": [ + { + "type": "shell", + "execute_command": "echo {{user `ssh_username`}} | {{ .Vars }} sudo -E -S sh '{{ .Path }}'", + "inline": [ + "mkdir -p /opt", + "chmod a+w /opt" + ] + }, + { + "type": "file", + "source": "tars/", + "destination": "/opt/" + }, + { + "type": "shell", + "execute_command": "echo {{user `ssh_username`}} | {{ .Vars }} sudo -E -S sh '{{ .Path }}'", + "inline": [ + "sudo tar -xzf /opt/athenz-ui-bin.tar.gz -C /opt/", + "sudo chmod 777 /opt/athenz-ui", + "mkdir -p /opt/athenz-ui/conf", + "mkdir -p /opt/athenz-ui/logs", + "sudo chmod 777 /opt/athenz-ui -R" + ] + }, + { + "type": "file", + "source": "build/bin/", + "destination": "/opt/athenz-ui/bin/" + }, + { + "type": "file", + "source": "build/conf/", + "destination": "/opt/athenz-ui/conf/" + }, + { + "type": "file", + "source": "build/service/", + "destination": "/opt/athenz-ui/" + }, + { + "type": "shell", + "execute_command": "echo {{user `ssh_username`}} | {{ .Vars }} sudo -E -S sh '{{ .Path }}'", + "inline": [ + "ls -ltr /opt/" + ] + }, + { + "type": "shell", + "scripts": [ + "packer/scripts/setup.sh" + ], + "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo -E '{{ .Path }}'" + } + ] +} diff --git a/aws-setup/ui-setup/packer/scripts/setup.sh b/aws-setup/ui-setup/packer/scripts/setup.sh new file mode 100755 index 00000000000..ccb3044c6a4 --- /dev/null +++ b/aws-setup/ui-setup/packer/scripts/setup.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +set -xe + +# install epel + +sudo yum repolist +sudo yum -y install epel-release + + +# install aws_cli + +echo "install aws" +sudo yum -y install python-pip +sudo pip install awscli +aws --version + +# install node + +sudo curl --silent --location https://rpm.nodesource.com/setup_6.x | sudo bash - +sudo yum -y install nodejs + +# setup our athenz group and user + +sudo groupadd athenz +sudo useradd -g athenz athenz-ui + +# setup our ui service + +sudo mkdir /etc/ui +sudo cp /opt/athenz-ui/ui.service /etc/ui/ui.service +sudo systemctl enable /etc/ui/ui.service +sudo cp /opt/athenz-ui/conf/ui-user /etc/sudoers.d/ + +#set up aws logs + +curl https://s3.amazonaws.com//aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -o /opt/athenz-ui/logs/awslogs-agent-setup.py + +# make sure all files are owned by our user/group + +sudo chown -R athenz-ui:athenz /opt/athenz-ui diff --git a/aws-setup/zms-setup/build/bin/add_user.sh b/aws-setup/zms-setup/build/bin/add_user.sh new file mode 100755 index 00000000000..538465fc01b --- /dev/null +++ b/aws-setup/zms-setup/build/bin/add_user.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +displayUsage() { + echo "add_user.sh [username] [bucket_name] "; +} + +if [ $# -ne 2 ] +then + displayUsage + exit 1 +fi + +adminUser=$1 +bucketName=$2 +passFile=/tmp/admin_pass + +aws s3 cp s3://$bucketName/admin_pass $passFile +adminPass=$(cat $passFile) + +sudo useradd $adminUser +echo $adminPass | sudo passwd $adminUser --stdin + +sudo rm $passFile \ No newline at end of file diff --git a/aws-setup/zms-setup/build/bin/aws_config.sh b/aws-setup/zms-setup/build/bin/aws_config.sh new file mode 100755 index 00000000000..3dcb21a48c7 --- /dev/null +++ b/aws-setup/zms-setup/build/bin/aws_config.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +aws_config_dir="$HOME/.aws" + +if [ -z "$HOME" ]; then + aws_config_dir="/athenz-zms/.aws" +fi + +echo "Configuring aws config in $aws_config_dir" + +if [ ! -d "$aws_config_dir" ]; then + mkdir $aws_config_dir +fi + +aws_config="[default]\nregion=$REGION" +echo -e $aws_config > $aws_config_dir/config + +aws configure set s3.signature_version s3v4 diff --git a/aws-setup/zms-setup/build/bin/aws_init.sh b/aws-setup/zms-setup/build/bin/aws_init.sh new file mode 100755 index 00000000000..049aac823b5 --- /dev/null +++ b/aws-setup/zms-setup/build/bin/aws_init.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Exposes bucket names based on account and region +# ENV +# ZMS_DATA_BUCKET_NAME +# ZMS_AUDIT_LOG_BUCKET_NAME +# REGION +# TRUST_STORE_PATH +# JDK_CA_CERTS_PATH +# KEY_STORE_PATH +# JDK_CA_CERTS_PWD +# RDS_MASTER +# RDS_REPLICA + +set -e + +export REGION=`curl http://169.254.169.254/latest/dynamic/instance-identity/document|grep region|awk -F\" '{print $4}'` +export ENV="dev" + +export ZMS_DATA_BUCKET_NAME="athenz-zms-data-bucket-name" +export ZMS_AUDIT_LOG_BUCKET_NAME="athenz-audit-log-bucket-name" +export DOMAIN_ADMIN="zms-admin" +export RDS_MASTER="zms-rds-database-cluster-endpoint" +export TRUST_STORE_PATH="/opt/zms/conf/zms_java_truststore.jks" +export ZMS_TRUST_STORE_PATH="/opt/zms/conf/zms_truststore.jks" +export JDK_CA_CERTS_PATH="/etc/alternatives/jre_1.8.0_openjdk/lib/security/cacerts" +export KEY_STORE_PATH="/opt/zms/conf/zms_keystore.pkcs12" +export JDK_CA_CERTS_PWD="changeit" +export DATASTORE_NAME="zmsserver" + + diff --git a/aws-setup/zms-setup/build/bin/aws_java_truststore_gen.sh b/aws-setup/zms-setup/build/bin/aws_java_truststore_gen.sh new file mode 100755 index 00000000000..6e6c8d9e2f8 --- /dev/null +++ b/aws-setup/zms-setup/build/bin/aws_java_truststore_gen.sh @@ -0,0 +1,60 @@ +#!/bin/bash +############# +# Usage: aws_java_truststore_gen.sh [jdk-ca-certs-path] [jdk-ca-certs-pwd] [bucket name] [trust store path] +# Downloads CA certs from S3 bucket. Creates pkcs12 truststore for jetty. +# Check for generated truststore: openssl pkcs12 -info -in /opt/zms/conf/ca.pkcs12 +############### + +display_usage() { + echo "aws_java_truststore_gen.sh [jdk-ca-certs-path] [jdk-ca-certs-pwd] [bucket name] [trust store path]"; + echo "example: aws_java_truststore_gen.sh /opt/jvm/cacerts changeit oath-aws-athenz-sys-auth-certsign-us-west-2 /opt/zms/conf/ca.pkcs12" +} + +cleanup() { + rm -f /tmp/service_rds_ca_certs + rm -f split_cacert-* +} + +if [ $# -ne 4 ] +then + display_usage + exit 1 +fi + +cleanup + +# define our S3 bucket filenames. we'll be using the same names +# when we store files locally + +rds_ca_certs=service_rds_ca_certs + +jdk_ca_certs_path=$1 +jdk_ca_certs_pwd=$2 +bucket_name=$3 +trust_store_path=$4 + +# download RDS CA certs from s3 bucket +# aws s3 client will automatically decrypt the data + +aws s3 cp s3://$bucket_name/$rds_ca_certs /tmp/$rds_ca_certs + +# first copy the jdk ca certs into our given filename + +cp $jdk_ca_certs_path $trust_store_path +rc=$?; if [[ $rc != 0 ]]; then cleanup; exit $rc; fi +chmod u+w $trust_store_path + +# split the CA certs and add them to the truststore + +csplit -f split_cacert- -s -z /tmp/$rds_ca_certs '/^-----BEGIN CERTIFICATE-----/' {*} +CERT_FILES=split_cacert-* +for file in $CERT_FILES +do + echo "Processing $file file..." + keytool -import -noprompt -alias $file -keystore $trust_store_path -file $file -storepass $jdk_ca_certs_pwd + rc=$?; if [[ $rc != 0 ]]; then cleanup; exit $rc; fi +done + +cleanup + +echo "successfully generated trust store" diff --git a/aws-setup/zms-setup/build/bin/aws_zms_keystore_gen.sh b/aws-setup/zms-setup/build/bin/aws_zms_keystore_gen.sh new file mode 100755 index 00000000000..e84e70e2049 --- /dev/null +++ b/aws-setup/zms-setup/build/bin/aws_zms_keystore_gen.sh @@ -0,0 +1,62 @@ +#!/bin/bash +############# +# Usage: aws_zms_keystore_gen.sh [bucket name] [key store path] +# Downloads encrypted server.key and server.cert from private S3 bucket. +# Decrypts and creates pkcs12 keystore for jetty. +# Assumes that this script runs on an instance with a role that has policy +# set to allow kms decrypt and read access to private S3 bucket. +# Check for generated keystore: openssl pkcs12 -info -in jetty.pkcs12 +############### + +display_usage() { + echo "aws_zms_keystore_gen.sh [bucket name] [key store path]"; + echo "example: aws_zms_keystore_gen.sh oath-aws-athenz-sys-auth-zms-prod-data-us-west-2 jetty.pkcs12" +} + +cleanup() { + rm -f /tmp/service_x509_* +} + +if [ $# -ne 2 ] +then + display_usage + exit 1 +fi + +cleanup + +# define our S3 bucket filenames. we'll be using the same names +# when we store files locally + +key_file=service_x509_key +cert_file=service_x509_cert +pwd_file=service_x509_store_pwd + +bucket_name=$1 +key_store_path=$2 + +# download server cert and key from private s3 bucket +# aws s3 client will automatically decrypt the data + +aws s3 cp s3://$bucket_name/$key_file /tmp/$key_file +aws s3 cp s3://$bucket_name/$cert_file /tmp/$cert_file + +# extract the password the keystore + +aws s3 cp s3://$bucket_name/$pwd_file /tmp/$pwd_file +key_store_pass=`cat /tmp/$pwd_file` + +# generate pkcs12 keystore using openssl + +openssl pkcs12 -export -inkey /tmp/$key_file -in /tmp/$cert_file -out $key_store_path -password pass:$key_store_pass -noiter -nomaciter +openssl_status=$? + +cleanup + +if [ ! $openssl_status -eq 0 ]; then + echo "failed to generate key store" + exit 1 +fi + +echo "successfully generated key store" + diff --git a/aws-setup/zms-setup/build/bin/aws_zms_truststore_gen.sh b/aws-setup/zms-setup/build/bin/aws_zms_truststore_gen.sh new file mode 100755 index 00000000000..16b4d327b90 --- /dev/null +++ b/aws-setup/zms-setup/build/bin/aws_zms_truststore_gen.sh @@ -0,0 +1,59 @@ +#!/bin/bash +############# +# Usage: aws_zms_truststore_gen.sh [bucket name] [trust store path] +# Downloads CA certs from S3 bucket. Creates pkcs12 truststore for jetty. +# Check for generated truststore: openssl pkcs12 -info -in /opt/zms/conf/ca.pkcs12 +############### + +display_usage() { + echo "aws_zms_truststore_gen.sh [bucket name] [trust store path]"; + echo "example: aws_zms_truststore_gen.sh oath-aws-athenz-sys-auth-certsign-us-west-2 /opt/zms/conf/ca.pkcs12" +} + +cleanup() { + rm -f /tmp/service_x509_ca_certs + rm -f split_cacert-* +} + +if [ $# -ne 2 ] +then + display_usage + exit 1 +fi + +cleanup + +# define our S3 bucket filenames. we'll be using the same names +# when we store files locally + +ca_certs_file=service_x509_ca_certs +pwd_file=service_x509_store_pwd + +bucket_name=$1 +trust_store_path=$2 + +# download CA certs from s3 bucket +# aws s3 client will automatically decrypt the data + +aws s3 cp s3://$bucket_name/$ca_certs_file /tmp/$ca_certs_file + +# extract the password the truststore + +aws s3 cp s3://$bucket_name/$pwd_file /tmp/$pwd_file +trust_store_pass=`cat /tmp/$pwd_file` + +# split the CA certs and add them to the truststore + +csplit -f split_cacert- -s -z /tmp/$ca_certs_file '/^-----BEGIN CERTIFICATE-----/' {*} +CERT_FILES=split_cacert-* +for file in $CERT_FILES +do + echo "Processing $file file..." + keytool -import -noprompt -alias $file -keystore $trust_store_path -file $file -storepass $trust_store_pass + rc=$?; if [[ $rc != 0 ]]; then cleanup; exit $rc; fi +done + +cleanup + +echo "successfully generated trust store" + diff --git a/aws-setup/zms-setup/build/bin/initialize_zms.sh b/aws-setup/zms-setup/build/bin/initialize_zms.sh new file mode 100755 index 00000000000..23a34db79bb --- /dev/null +++ b/aws-setup/zms-setup/build/bin/initialize_zms.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +Usage: initialize_zms.sh + +# Runs aws_zms_truststore_gen.sh to get trust store +# Runs ws_java_truststore_gen.sh to get java trust store +# Runs aws_zms_keystore_gen.sh to generate key store. + +set -e + +echo "creating aws config" +/opt/zms/bin/aws_config.sh + +echo "initializing aws cloudwatch log setup" +sudo python /opt/zms/logs/awslogs-agent-setup.py -n -r $REGION -c /opt/zms/conf/awslogs.conf + +cd /opt/zms/temp + +echo "generating zms trust store /opt/zms/bin/aws_zms_truststore_gen.sh $ZMS_DATA_BUCKET_NAME $ZMS_TRUST_STORE_PATH" +rm -f $ZMS_TRUST_STORE_PATH +/opt/zms/bin/aws_zms_truststore_gen.sh $ZMS_DATA_BUCKET_NAME $ZMS_TRUST_STORE_PATH + +echo "generating java trust store $JDK_CA_CERTS_PATH $JDK_CA_CERTS_PWD $ZMS_DATA_BUCKET_NAME $TRUST_STORE_PATH" +rm -f $TRUST_STORE_PATH +/opt/zms/bin/aws_java_truststore_gen.sh $JDK_CA_CERTS_PATH $JDK_CA_CERTS_PWD $ZMS_DATA_BUCKET_NAME $TRUST_STORE_PATH + +echo "generating zms key store /opt/zms/bin/aws_zms_keystore_gen.sh $ZMS_DATA_BUCKET_NAME $KEY_STORE_PATH" +rm -f $KEY_STORE_PATH +/opt/zms/bin/aws_zms_keystore_gen.sh $ZMS_DATA_BUCKET_NAME $KEY_STORE_PATH + +echo "Adding domain admin /opt/zms/bin/add_user.sh $DOMAIN_ADMIN $ZMS_DATA_BUCKET_NAME" +/opt/zms/bin/add_user.sh $DOMAIN_ADMIN $ZMS_DATA_BUCKET_NAME + + diff --git a/aws-setup/zms-setup/build/bin/zms.sh b/aws-setup/zms-setup/build/bin/zms.sh new file mode 100755 index 00000000000..13dd1c579e5 --- /dev/null +++ b/aws-setup/zms-setup/build/bin/zms.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -e + +source /opt/zms/bin/aws_init.sh + +/opt/zms/bin/initialize_zms.sh +cd /opt/zms + +# setup our database cluster endpoint and other environment +# specific settings. us-west-2 is our primary region while + +# us-east-1 is our backup read-only region + +JAVA_OPTS="-XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:+PrintGCDetails -Xloggc:/opt/zms/logs/gc.log" +JAVA_OPTS="${JAVA_OPTS} -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation" +JAVA_OPTS="${JAVA_OPTS} -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=4M" +JAVA_OPTS="${JAVA_OPTS} -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/zms/logs" + +java -server $JAVA_OPTS \ + -Dathenz.root_dir=/opt/zms \ + -Dathenz.zms.root_dir=/opt/zms \ + -Dlogback.configurationFile=/opt/zms/conf/logback.xml \ + -Dathenz.prop_file=/opt/zms/conf/athenz.properties \ + -Dathenz.zms.prop_file=/opt/zms/conf/zms.properties \ + -Dathenz.aws.zms.bucket_name=$ZMS_DATA_BUCKET_NAME \ + -Dathenz.ssl_key_store_password_appname=$ZMS_DATA_BUCKET_NAME \ + -Dathenz.ssl_trust_store_password_appname=$ZMS_DATA_BUCKET_NAME \ + -Dathenz.zms.jdbc_store=jdbc:mysql://${RDS_MASTER}:3306/${DATASTORE_NAME} \ + -Dathenz.zms.jdbc_app_name=$ZMS_DATA_BUCKET_NAME \ + -Dathenz.zms.aws_rds_master_instance=$RDS_MASTER \ + -Dathenz.aws.s3.region=$REGION \ + -Dathenz.zms.read_only_mode=false \ + -classpath ":/opt/zms/jars/*:" \ + com.yahoo.athenz.container.AthenzJettyContainer diff --git a/aws-setup/zms-setup/build/conf/athenz.properties b/aws-setup/zms-setup/build/conf/athenz.properties new file mode 100755 index 00000000000..1939587d449 --- /dev/null +++ b/aws-setup/zms-setup/build/conf/athenz.properties @@ -0,0 +1,163 @@ +# Athenz Jetty Container properties file. +# If there is a value specified in the commented property line, +# then it indicates the default value + +# The TLS port that Jetty will listen on for HTTPS connection +athenz.tls_port=4443 + +# The standard HTTP port for Jetty - disabled by default +athenz.port=0 + +# Port for requesting /status health check. If this setting is +# not specified, then the request will be handled by either http +# or https ports specified in the configuration. However, if this +# status port is specified and is different than the configured +# http and https ports, then /status endpoint will only be handled +# on this port and all other requests will be rejected. Similarly, +# /status endpoint will not be allowed on configured http/https +# ports. The status port will be either http or https depending +# which port is specified for data access. If both http and https +# ports are specified, https will be selected for the protocol. +athenz.status_port=8443 + +# Set the number of days before rotated access log files are deleted +athenz.access_log_retain_days=31 + +# Format of the access log filename +athenz.access_log_name=access.yyyy_MM_dd.log + +# If specified, the server will use SLF4J logger with the specified name +# to log events instead of using Jetty's NCSARequestLog class. +# The administrator then must configure the specified logger in the logback.xml +athenz.access_slf4j_logger= + +# Directory to store access log files +athenz.access_log_dir=/opt/zms/logs + +# Key Manager password +#athenz.ssl_key_manager_password= + +# The path to the keystore file that contains the server's certificate +athenz.ssl_key_store=/opt/zms/conf/zms_keystore.pkcs12 + +# Specifies the type for the keystore specified in the +# athenz.ssl_key_store property +athenz.ssl_key_store_type=PKCS12 + +# Password for the keystore specified in the athenz.ssl_key_store property +athenz.ssl_key_store_password=service_x509_store_pwd + +# The path to the trust store file that contains CA certificates +# trusted by this Jetty instance +athenz.ssl_trust_store=/opt/zms/conf/zms_truststore.jks + +# Specifies the type for the truststore specified in the +# athenz.ssl_trust_store property +athenz.ssl_trust_store_type=JKS + +# Password for the truststore specified in the athenz.ssl_trust_store property +athenz.ssl_trust_store_password=service_x509_store_pwd + +# Specifies whether or not for data requests the server +# would require TLS client authentication rather than +# just wanting it +athenz.ssl_need_client_auth=false + +# Configure if client TLS renegotiation is allowed or not +athenz.ssl_renegotiation_allowed=false + +# Enable OCSP support +#athenz.ssl_enable_ocsp=false + +# Private key store to extract the passwords defined for +# java keystore and truststore +athenz.private_keystore_factory_class=com.yahoo.athenz.auth.impl.aws.AwsPrivateKeyStoreFactory + +# Specifies the truststore used by java clients when communicating +# with other AWS services like S3 or RDS. This should be the +# JDK shipped truststore + AWS RDS CA truststore +javax.net.ssl.trustStore=/opt/zms/conf/zms_java_truststore.jks +javax.net.ssl.trustStorePassword=changeit + +# List of excluded cipher suites from TLS negotiation +#athenz.ssl_excluded_cipher_suites= + +# List of cipher suites supported for TLS negotiation +athenz.ssl_included_cipher_suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA + +#Comma separated list of excluded ssl protocols +#athenz.ssl_excluded_protocols=SSLv2,SSLv3 + +# In milliseconds how long that connector will be allowed to +# remain idle with no traffic before it is shutdown +athenz.http_idle_timeout=30000 + +# Boolean setting to specify whether or not the server should +# send the Server header in response +athenz.http_send_server_version=false + +# Boolean setting to specify whether or not the server should +# include the Date in HTTP headers +athenz.http_send_date_header=false + +# The size in bytes of the output buffer used to aggregate HTTP output +#athenz.http_output_buffer_size=32768 + +# The maximum allowed size in bytes for a HTTP request header +#athenz.http_reqeust_header_size=8192 + +# The maximum allowed size in bytes for a HTTP response header +#athenz.http_response_header_size=8192 + +# For HTTP access specifies the IP address/Host for service to listen on. +# This could be necessary, for example, if the system administrator +# wants some proxy server (e.g. ATS) to handle TLS traffic and configure +# Jetty to listen on 127.0.0.1 loopback address only for HTTP connections +# from that proxy server +#athenz.listen_host= + +# Boolean flag to indicate whether or not the container should honor +# the Keep Alive connection option or just connections right away +#athenz.keep_alive=false + +# Max number of threads Jetty is allowed to spawn to handle incoming requests +athenz.http_max_threads=1024 + +# Specify the FQDN/hostname of the server. This will be reported as part +# of the server banner notification in logs +#athenz.hostname= + +# Default home directory for embedded Jetty Deployer. The container will look +# for any servlets in the webapps subdirectory of the configured directory +athenz.jetty_home=/opt/zms + +# Boolean flag to enable debug log entries when deploying webapps +#athenz.debug=false + +# Comma separated liste of uris that are accessed by health check +# system. Used by the simple file based health check filter that +# returns 200/404 if the file exists or not +athenz.health_check_uri_list=/status + +# Directory name where the files specified in the athenz.health_check_uri_list +# setting are checked for +athenz.health_check_path=/opt/zms + +# Enable Proxy Protocol (used by HAProxy and environments such as Amazon Elastic Cloud) +# for the jetty container. +athenz.proxy_protocol=true + +# Enable rate limit +athens.server_common.ratelimit.enable_ratelimit=true + +# Ratelimit factory class name +athenz.ratelimit_factory_class=com.yahoo.athenz.common.filter.impl.NoOpRateLimitFactory + +# Ratelimit whitelisted role names comma delimited +#athens.server_common.ratelimit.whitelist_roles= + +# Ratelimit limit +athens.server_common.ratelimit.limit_count=100 + +# Ratelimit limit per resource +athens.server_common.ratelimit.rules=/access/:25,/sys/:3 diff --git a/aws-setup/zms-setup/build/conf/awslogs.conf b/aws-setup/zms-setup/build/conf/awslogs.conf new file mode 100755 index 00000000000..73e10c8b1a6 --- /dev/null +++ b/aws-setup/zms-setup/build/conf/awslogs.conf @@ -0,0 +1,26 @@ +[general] +state_file = /var/awslogs/state/agent-state + +[syslog] +file = /var/log/messages +log_group_name = athenz-zms-service-syslog +log_stream_name = {instance_id} +datetime_format = %b %d %H:%M:%S + +[access] +file = /opt/zms/logs/access*.log +log_group_name = athenz-zms-service-access +log_stream_name = {instance_id} +datetime_format = %b %d %H:%M:%S + +[server] +file = /opt/zms/logs/zms_server/server*.log +log_group_name = athenz-zms-service-server +log_stream_name = {instance_id} +datetime_format = %b %d %H:%M:%S + +[gc] +file = /opt/zms/logs/gc.log.* +log_group_name = athenz-zms-service-gc +log_stream_name = {instance_id} +datetime_format = %b %d %H:%M:%S \ No newline at end of file diff --git a/aws-setup/zms-setup/build/conf/logback.xml b/aws-setup/zms-setup/build/conf/logback.xml new file mode 100755 index 00000000000..e714e369e58 --- /dev/null +++ b/aws-setup/zms-setup/build/conf/logback.xml @@ -0,0 +1,49 @@ + + + + + + + + + ${LOG_DIR}/server.log + true + + + ${LOG_DIR}/server.%d.log + 7 + true + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg%n + + + + + + + ${LOG_DIR}/audit.log + true + + + ${LOG_DIR}/audit.%d.log + 30 + true + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg%n + + + + + + + + + + + + + \ No newline at end of file diff --git a/aws-setup/zms-setup/build/conf/zms-user b/aws-setup/zms-setup/build/conf/zms-user new file mode 100755 index 00000000000..40eccf6448f --- /dev/null +++ b/aws-setup/zms-setup/build/conf/zms-user @@ -0,0 +1 @@ +athenz-zms ALL=(ALL) NOPASSWD: ALL \ No newline at end of file diff --git a/aws-setup/zms-setup/build/conf/zms.properties b/aws-setup/zms-setup/build/conf/zms.properties new file mode 100755 index 00000000000..ba7fa6a9e12 --- /dev/null +++ b/aws-setup/zms-setup/build/conf/zms.properties @@ -0,0 +1,352 @@ +# Athenz ZMS Servlet properties file. +# If there is a value specified in the commented property line, +# then it indicates the default value + +# Comma separated list of authority implementation classes to support +# authenticating principals in ZMS +athenz.zms.authority_classes=com.yahoo.athenz.auth.impl.PrincipalAuthority,com.yahoo.athenz.auth.impl.UserAuthority + +# Principal Authority class. If defined and the caller asks for the header +# name for the getUserToken api, the header from this authority will be +# returned in the response. This class must be one of the classes listed +# in the athenz.zms.authority_classes setting +#athenz.zms.principal_authority_class= + +# Specifies the user domain name for the current installation +#athenz.user_domain=user +#athens.auth_core.bouncer.domain=user + +# Specifies the user domain alias name for the current installation +#athenz.user_domain_alias=yby + +# Specifies the personal home domain name for the current installation +athenz.home_domain=home + +# Specifies the factory class that implements the Metrics interface +# used by the ZMS Server to report stats +athenz.zms.metric_factory_class=com.yahoo.athenz.common.metrics.impl.NoOpMetricFactory + +# Specifies the factory class that implements the AuditLoggerFactory +# interface used by the ZMS Server to log all changes to domain +# data for auditing purposes +athenz.zms.audit_logger_factory_class=com.yahoo.athenz.common.server.log.impl.DefaultAuditLoggerFactory + +# Specifies the factory class that implements the PrivateKeyStoreFactory +# interface used by the ZMS Server to get access to its host specific +# private key +athenz.zms.private_key_store_factory_class=com.yahoo.athenz.auth.impl.aws.AwsPrivateKeyStoreFactory + +# If the datastore does not contain any domains during startup, +# the server will automatically create sys, sys.auth and user +# domains and assign the specified users (comma separated list) +# as the administrator for those domains +athenz.zms.domain_admin=user.zms-admin + +# If File Private Key store implementation is used in the Server, +# this setting specifies the path to the PEM encoded ZMS Server +# private key file (both RSA and EC privates keys are supported) +#athenz.auth.private_key_store.private_key=/opt/zms/var/zms_server/keys/zms_private.pem + +# If File Private Key store implementation is used in the Server, +# this setting specifies the key identifier for the private key +# configured by the athenz.auth.private_key_store.private_key +# property +#athenz.auth.private_key_store.private_key_id=0 + +# Specify the FQDN/hostname of the server. This value will be used as the +# h parameter in the ZMS generated UserTokens +#athenz.zms.hostname= + +# Specifies the authorized service json configuration file path. +#athenz.zms.authz_service_fname= + +# Specifies the path to the solution templates json document +#athenz.zms.solution_templates_fname= + +# In case there is a concurrent update conflict, the server will retry +# the operation multiple times until this timeout is reached before +# returning a conflict status code back to the client +#athenz.zms.conflict_retry_timeout=60 + +# When ZMS determines that updating a domain data tables will cause a +# concurrent update issue and needs to retry the operation, it will sleep +# configured number of milliseconds before retrying +#athenz.zms.retry_delay_timeout=50 + +# This setting specifies the number of seconds how long the signed +# policy documents are valid for +#athenz.zms.signed_policy_timeout=604800 + +# The number of milliseconds to sleep between runs of the idle object +# evictor thread. When non-positive, no idle object evictor thread +# will be run. The pool default is -1, but we're using 30 minutes to +# make sure the evictor thread is running | +#athenz.db.pool_evict_idle_interval=1800000 + +# The minimum amount of time (in milliseconds) an object may sit +# idle in the pool before it is eligible for eviction by the idle +# object evictor (if any) +#athenz.db.pool_evict_idle_timeout=1800000 + +# The maximum number of connections that can remain idle in the pool, +# without extra ones being released, or negative for no limit +#athenz.db.pool_max_idle=8 + +# The maximum number of active connections that can be allocated +# from this pool at the same time, or negative for no limit +#athenz.db.pool_max_total=8 + +# The maximum lifetime in milliseconds of a connection. After this +# time is exceeded the connection will fail the next activation, +# passivation or validation test. A value of zero or less means the +# connection has an infinite lifetime +#athenz.db.pool_max_ttl=600000 + +# The maximum number of milliseconds that the pool will wait +# (when there are no available connections) for a connection to be +# returned before throwing an exception, or -1 to wait indefinitely +#athenz.db.pool_max_wait=-1 + +# The minimum number of connections that can remain idle in the pool, +# without extra ones being created, or zero to create none +#athenz.db.pool_min_idle=0 + +# The maximum number of seconds that the server should wait +# for the store connection object to return its results +#athenz.zms.store_operation_timeout=60 + +# Specifies the factory class that implements the ObjectStoreFactory +# interface used by the ZMS Server to store its data. In production, +# this is typically the jdbc/mysql object store while for tests it's +# the file object store +athenz.zms.object_store_factory_class=com.yahoo.athenz.zms.store.impl.JDBCObjectStoreFactory + +# If the athenz.zms.object_store_factory_class property is using +# the file object store factory, then this setting specifies +# the subdirectory name where domain files will be stored. +# The parent directory is identified by the athenz.zms.file_store_path +# property +#athenz.zms.file_store_path=/opt/zms/var/zms_server + +# If the athenz.zms.object_store_factory_class property is using +# the file object store factory, then this setting specifies +# the directory name where file store subdirectory will +# be created to store domain files. The subdirectory is identified +# by the athenz.zms.file_store_name property +#athenz.zms.file_store_name=zms_root + +# If the athenz.zms.object_store_factory_class property is using +# the jdbc object store factory identified with +# com.yahoo.athenz.zms.store.impl.JDBCObjectStoreFactory, then +# this setting specifies JDBC URL where the ZMS Server will store its data. +# The database server must be initialized with the ZMS +# server schema. For example, jdbc:mysql://localhost:3306/zms +# specifies a database called zms configured within a +# MySQL instance +#athenz.zms.jdbc_store= + +# If the athenz.zms.object_store_factory_class property is using +# the jdbc/mysql object store factory then this setting +# specifies the name of the user that has full access to the configured +# ZMS server database +athenz.zms.jdbc_user=athenz-zms + +# If the athenz.zms.object_store_factory_class property is using +# the jdbc/mysql object store factory then this setting +# specifies the password key for the jdbc user that has been granted full +# access to the configured ZMS server database. The configured +# private key store will be called with the value of the key to +# retrieve the password to authenticate requests against the +# configured MySQL server. +athenz.zms.jdbc_password=db_user_data + +# If the athenz.zms.object_store_factory_class property is using +# the jdbc/mysql object store factory then this setting specifies +# JDBC URL for slave databases that replicate ZMS Server's +# domain data. If configured, ZMS Server will use this database +# instance for any read only operation. It has the same syntax +# as the athenz.zms.jdbc_store property. +#athenz.zms.jdbc_ro_store= + +# If the athenz.zms.jdbc_ro_store is configured then this property is +# the name of the user that has full access to the zms database +# if this property is not specified but athenz.zms.jdbc_ro_store +# is configured, the server will use the value of the +# athenz.zms.jdbc_user property. +#athenz.zms.jdbc_ro_user= + +# If the athenz.zms.jdbc_ro_store is configured then this property +# specifies the password key for the jdbc user that has been granted +# full access to the configured zms database. If this property is not +# specified but athenz.zms.jdbc_ro_store is configured, the server +# will use the value of the athenz.zms.jdbc_password property. +# The configured private key store will be called with the value of +# the key to retrieve the password to authenticate requests against +# the configured MySQL server. +#athenz.zms.jdbc_ro_password= + +# If using the jdbc connector (either mysql or aws) for zms +# data storage, this property specifies if the jdbc client +# should establish an SSL connection to the database server or not +athenz.zms.jdbc_use_ssl=false + +# if using the jdbc connector (either mysql or aws) for zms +# data storage and the athenz.zms.jdbc_use_ssl property is set +# to true, this property specifies whether or not the jdbc client +# must verify the server certificate or not +athenz.zms.jdbc_verify_server_certificate=true + +# If the athenz.zms.object_store_factory_class property is using +# the aws rds mysql object store factory identified with +# com.yahoo.athenz.zms.store.impl.AWSObjectStoreFactory, then +# this setting specifies AWS RDS instance hostname. +# The database server must be initialized with the ZMS +# server schema. +#athenz.zms.aws_rds_master_instance= + +# If the athenz.zms.object_store_factory_class property is using +# the aws rds mysql object store then this setting specifies +# the database user configured with IAM Role AWS authentication +# and full access to the zms store database +athenz.zms.aws_rds_user=zms + +# If the athenz.zms.object_store_factory_class property is using +# the aws rds mysql object store then this setting specifies +# the IAM role that has been enabled for authentication +athenz.zms.aws_rds_iam_role=athenz.zms-service + +# If the athenz.zms.object_store_factory_class property is using +# the aws rds mysql object store then this setting specifies +# the port number for the RDL database instance +athenz.zms.aws_rds_master_port=3306 + +# If the athenz.zms.object_store_factory_class property is using +# the aws rds mysql object store then this setting specifies +# the database engine used in rds +athenz.zms.aws_rds_engine=mysql + +# If the athenz.zms.object_store_factory_class property is using +# the aws rds mysql object store then this setting specifies +# the database name in rds +athenz.zms.aws_rds_database=zmsstore + +# If the athenz.zms.object_store_factory_class property is using +# the aws rds mysql object store then this setting specifies +# in seconds how often to update the aws credentials for the IAM role +athenz.zms.aws_rds_creds_refresh_time=300 + +# The number of seconds ZMS issued User Tokens are valid for +#athenz.zms.user_token_timeout=3600 + +# Boolean setting to configure whether or not virtual domains are +# supported or not. These are domains created in the user's own +# "user" namespace +#athenz.zms.virtual_domain_support=true + +# If virtual domain support is enabled, this setting specifies the +# number of sub domains in the user's virtual namespace that are +# allowed to be created. Value of 0 indicates no limit +#athenz.zms.virtual_domain_limit=5 + +# Number of bytes allowed to be specified in a domain name. +# This limit includes all subdomains as well. For example, +# athenz.storage.mysql domains length is 20. +#athenz.zms.domain_name_max_len=128 + +# Boolean setting to configure whether or not unique product +# IDs are required for top level domains +athenz.zms.product_id_support=false + +# Number of seconds the authentication library will honor +# token's expiration timeout. +#athenz.token_max_expiry=2592000 + +# For read operations allow tokens with no expiry +athenz.token_no_expiry=true + +# User Authority - if UserAuthority is enabled as one of the authenticating +# authorities in the ZMS Server, this setting provides the pam service +# name used when validating the user specified password +#athenz.auth.user.pam_service_name=login + +# Role Authority - when validating Role Tokens, this setting specifies the +# number seconds the library will allow the token to have a creation time +# in the future to accommodate time differences between server and client. +#athenz.auth.role.token_allowed_offset=300 + +# Role Authority - when authenticating principals based on the Role Token +# this setting specifies what HTTP header name in the request contains +# the token +#athenz.auth.role.header=Athenz-Role-Auth + +# Principal Authority - when validating User/Service Tokens, this setting +# specifies the number seconds the library will allow the token to have +# a creation time in the future to accommodate time differences between +# server and client. +#athenz.auth.principal.token_allowed_offset=300 + +# Principal Authority - when authenticating principals based on their +# User/Service Tokens, this setting specifies what HTTP header name in +# the request contains the token +#athenz.auth.principal.header=Athenz-Principal-Auth + +# Principal Authority - when authenticating principals based on their +# User/Service Tokens. this setting specifies whether or not to validate +# if the IP address of the incoming connection matches to the IP address +# in the token. The possible values are: OPS_ALL, OPS_NONE, OPS_WRITE +# OPS_WRITE indicates that only write/update operation will enforce +# this check. +#athenz.auth.principal.remote_ip_check_mode=OPS_WRITE + +# If the ZMS webapp is deployed along other webapps that may +# run on non-TLS ports, this setting forces that requests to +# ZMS are only accepted on secure TLS ports. +#athenz.zms.secure_requests_only=true + +# Quota Support: boolean value defining whether or not quota +# check is enabled. +athenz.zms.quota_check=true + +# Quota Support: default number of roles allowed to be created +# in a given domain. +athenz.zms.quota_role=1000 + +# Quota Support: default number of members a single role may have +athenz.zms.quota_role_member=500 + +# Quota Support: default number of polices allowed to be created +# in a given domain. +athenz.zms.quota_policy=1000 + +# Quota Support: default number of assertions each policy may have +athenz.zms.quota_assertion=500 + +# Quota Support: default number of services allowed to be created +# in a given domain. +athenz.zms.quota_service=250 + +# Quota Support: default number of hosts each service may have +athenz.zms.quota_service_host=100 + +# Quota Support: default number of public keys each service may have +athenz.zms.quota_public_key=100 + +# Quota Support: default number of entities allowed to be created +# in a given domain +athenz.zms.quota_entity=100 + +# Quota Support: default number of sub-domains each top level +# domain allowed to have. +athenz.zms.quota_subdomain=100 + +# Comma separated list of URIs that require authentication according to the RDL +# but we want the server to make the authentication as optional. The URI can +# include regex values based on + character to match resource URIs +# for example, /zms/v1/domain/.+/service +athenz.zms.no_auth_uri_list=/zms/v1/status + +# Comma separated list of principals to be excluded from +# certificate authority validation. This would include +# Athenz UI and Proxy services +athenz.auth.certificate.excluded_principals= + diff --git a/aws-setup/zms-setup/build/service/zms.service b/aws-setup/zms-setup/build/service/zms.service new file mode 100755 index 00000000000..7e2d27af6c5 --- /dev/null +++ b/aws-setup/zms-setup/build/service/zms.service @@ -0,0 +1,12 @@ +[Unit] +Description=Athenz ZMS Service +Wants=network-online.target ntpd.service +After=network-online.target + +[Service] +ExecStart=/opt/zms/bin/zms.sh +Restart=on-failure +RestartSec=20 + +[Install] +WantedBy=multi-user.target diff --git a/aws-setup/zms-setup/cloud-formation/athens-zms-aws-resource-setup.yaml b/aws-setup/zms-setup/cloud-formation/athens-zms-aws-resource-setup.yaml new file mode 100755 index 00000000000..bdf9546c521 --- /dev/null +++ b/aws-setup/zms-setup/cloud-formation/athens-zms-aws-resource-setup.yaml @@ -0,0 +1,609 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: 'Athenz ZMS standard 2 Availabilty zone configuration template' +Parameters: + ZMSServiceName: + Type: String + Description: The service name for ZMS server + Default: "zms" + ZMSVPCCidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the ZMS VPC. + Default: "10.0.0.0/20" + PrivateSubnet01CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Private Subnet Zone 1. + Default: "10.0.0.0/22" + PrivateSubnet02CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Private Subnet Zone 2. + Default: "10.0.4.0/22" + PublicSubnet01CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Public Subnet Zone 1. + Default: "10.0.8.0/22" + PublicSubnet02CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Public Subnet Zone 2. + Default: "10.0.12.0/22" + GroupName: + Type: String + Description: The Athens domain for the account + Default: "Athenz" + Environment: + Type: String + Description: The environment ZMS is running in + AllowedValues: + - prod + - stage + - dev + S3AccessLogBucketName: + Type: String + Description: S3 bucket name to store access logs + Route53HostedZoneName: + Type: String + Description: The hosted zone name to place a CNAME entry for. Must end with a period. Empty string means do not create one. + Route53RecordName: + Type: String + Description: The hosted records to be added +Conditions: + CreateDNSRecordSet: !Not [!Equals [ !Ref Route53HostedZoneName, '']] + + +Resources: + ZMSVPC: + Type: 'AWS::EC2::VPC' + Properties: + CidrBlock: !Ref 'ZMSVPCCidrBlock' + EnableDnsSupport: true + EnableDnsHostnames: true + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZMSServiceName} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet01: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PrivateSubnet01CidrBlock' + VpcId: !Ref 'ZMSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZMSServiceName}-${AWS::Region}a-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet02: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 1 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PrivateSubnet02CidrBlock' + VpcId: !Ref 'ZMSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZMSServiceName}-${AWS::Region}b-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet01: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PublicSubnet01CidrBlock' + VpcId: !Ref 'ZMSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZMSServiceName}-${AWS::Region}a-public + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet02: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 1 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PublicSubnet02CidrBlock' + VpcId: !Ref 'ZMSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZMSServiceName}-${AWS::Region}b-public + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + Nacl: + Type: "AWS::EC2::NetworkAcl" + Properties: + VpcId: !Ref 'ZMSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZMSServiceName} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + NetworkAclEntry01: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '100' + Protocol: "6" + RuleAction: allow + CidrBlock: !Ref 'ZMSVPCCidrBlock' + PortRange: + From: '22' + To: '22' + NetworkAclEntry02: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '110' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '4443' + To: '4443' + NetworkAclEntry03: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '120' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '8443' + To: '8443' + NetworkAclEntry04: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '130' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '3306' + To: '3306' + NetworkAclEntry05: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '140' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '80' + To: '80' + NetworkAclEntry06: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '150' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '443' + To: '443' + NetworkAclEntry07: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '160' + Protocol: "17" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '123' + To: '123' + NetworkAclEntry08: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '200' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '1024' + To: '65535' + NetworkAclEntry09: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '100' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '22' + To: '22' + NetworkAclEntry10: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '110' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '4443' + To: '4443' + NetworkAclEntry11: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '120' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '8443' + To: '8443' + NetworkAclEntry12: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '130' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '3306' + To: '3306' + NetworkAclEntry13: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '140' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '80' + To: '80' + NetworkAclEntry14: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '160' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '443' + To: '443' + NetworkAclEntry15: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '150' + Protocol: "17" + RuleAction: allow + CidrBlock: !Ref 'ZMSVPCCidrBlock' + PortRange: + From: '123' + To: '123' + NetworkAclEntry16: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '200' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '1024' + To: '65535' + PrivateSubnet01Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PrivateSubnet01' + NetworkAclId: !Ref 'Nacl' + PrivateSubnet02Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PrivateSubnet02' + NetworkAclId: !Ref 'Nacl' + PublicSubnet01Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PublicSubnet01' + NetworkAclId: !Ref 'Nacl' + PublicSubnet02Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PublicSubnet02' + NetworkAclId: !Ref 'Nacl' + InternetGateway: + Type: "AWS::EC2::InternetGateway" + Properties: + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZMSServiceName} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + VPCGatewayAttachment: + Type: "AWS::EC2::VPCGatewayAttachment" + Properties: + InternetGatewayId: !Ref 'InternetGateway' + VpcId: !Ref 'ZMSVPC' + PublicSubnet01NatGateway: + Type: "AWS::EC2::NatGateway" + Properties: + AllocationId: !GetAtt PublicSubnet01EIP.AllocationId + SubnetId: !Ref 'PublicSubnet01' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZMSServiceName}-${AWS::Region}a + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet01EIP: + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + PublicSubnet02NatGateway: + Type: "AWS::EC2::NatGateway" + Properties: + AllocationId: !GetAtt PublicSubnet02EIP.AllocationId + SubnetId: !Ref 'PublicSubnet02' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZMSServiceName}-${AWS::Region}b + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet02EIP: + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + PublicSubnetRouteTable: + Type: "AWS::EC2::RouteTable" + Properties: + VpcId: !Ref 'ZMSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZMSServiceName}-${AWS::Region}-public + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + GatewayRoute: + Type: "AWS::EC2::Route" + Properties: + DestinationCidrBlock: '0.0.0.0/0' + GatewayId: !Ref 'InternetGateway' + RouteTableId: !Ref 'PublicSubnetRouteTable' + DependsOn: VPCGatewayAttachment + PrivateSubnet01RouteTable: + Type: "AWS::EC2::RouteTable" + Properties: + VpcId: !Ref 'ZMSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZMSServiceName}-${AWS::Region}a-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet01Route: + Type: "AWS::EC2::Route" + Properties: + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'PublicSubnet01NatGateway' + RouteTableId: !Ref 'PrivateSubnet01RouteTable' + PrivateSubnet02RouteTable: + Type: "AWS::EC2::RouteTable" + Properties: + VpcId: !Ref 'ZMSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZMSServiceName}-${AWS::Region}b-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet02Route: + Type: "AWS::EC2::Route" + Properties: + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'PublicSubnet02NatGateway' + RouteTableId: !Ref 'PrivateSubnet02RouteTable' + DependsOn: VPCGatewayAttachment + PublicSubnet01RouteTableAssociaton: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PublicSubnetRouteTable' + SubnetId: !Ref 'PublicSubnet01' + PublicSubnet02RouteTableAssociaton: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PublicSubnetRouteTable' + SubnetId: !Ref 'PublicSubnet02' + PrivateSubnet01RouteTableAssociation: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PrivateSubnet01RouteTable' + SubnetId: !Ref 'PrivateSubnet01' + PrivateSubnet02RouteTableAssociation: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PrivateSubnet02RouteTable' + SubnetId: !Ref 'PrivateSubnet02' + ZMSELBSecurityGroup: + Type: "AWS::EC2::SecurityGroup" + Properties: + GroupName: !Sub ${GroupName}-${Environment}-elb-sg-${ZMSServiceName}-${AWS::Region} + GroupDescription: 'ZMS public elb security group' + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: '4443' + ToPort: '4443' + CidrIp: '0.0.0.0/0' + VpcId: !Ref 'ZMSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-elb-${ZMSServiceName}-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + ZMSServerSecurityGroup: + Type: "AWS::EC2::SecurityGroup" + Properties: + GroupName: !Sub ${GroupName}-${Environment}-server-sg-${ZMSServiceName}-${AWS::Region} + GroupDescription: 'ZMS public server security group' + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: '4443' + ToPort: '4443' + CidrIp: '0.0.0.0/0' + - IpProtocol: tcp + FromPort: '8443' + ToPort: '8443' + CidrIp: !Ref 'ZMSVPCCidrBlock' + VpcId: !Ref 'ZMSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-server-${ZMSServiceName}-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + ZMSLoadBalancer: + Type: "AWS::ElasticLoadBalancing::LoadBalancer" + Properties: + HealthCheck: + HealthyThreshold: 2 + Interval: 5 + Target: !Sub HTTPS:8443/${ZMSServiceName}/v1/status + Timeout: 3 + UnhealthyThreshold: 4 + Listeners: + - InstancePort: 4443 + InstanceProtocol: TCP + LoadBalancerPort: 4443 + Protocol: TCP + Policies: + - PolicyName: "EnableProxyProtocol" + PolicyType: "ProxyProtocolPolicyType" + Attributes: + - Name: ProxyProtocol + Value: 'true' + InstancePorts: + - '4443' + LoadBalancerName: !Sub ${Environment}-elb-${ZMSServiceName}-${AWS::Region} + Scheme: 'internet-facing' + ConnectionDrainingPolicy: + Enabled: 'true' + Timeout: '60' + CrossZone: true + SecurityGroups: + - !Ref ZMSELBSecurityGroup + Subnets: + - !Ref 'PublicSubnet01' + - !Ref 'PublicSubnet02' + AccessLoggingPolicy: + S3BucketName: !Ref S3AccessLogBucketName + S3BucketPrefix: !Sub elb-${ZMSServiceName} + Enabled: 'true' + EmitInterval: '5' + Tags: + - Key: Name + Value: !Sub ${Environment}-elb-ZMS-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + ZMSRecordSet: + Type: AWS::Route53::RecordSet + Condition: CreateDNSRecordSet + Properties: + Comment: CNAME record for the ZMS Server. + HostedZoneName: !Ref Route53HostedZoneName + Name: !Ref Route53RecordName + TTL: 60 + Type: CNAME + ResourceRecords: + - !GetAtt ZMSLoadBalancer.DNSName +Outputs: + ZMSVPCID: + Description: The ID of the ZMS VPC + Value: !Ref ZMSVPC + Export: + Name: !Sub "${AWS::StackName}-VPCID" + PrivateSubnet01ID: + Description: TThe ID of Private Subnet Availability Zone 1 in ZMS VPC + Value: !Ref PrivateSubnet01 + Export: + Name: !Sub "${AWS::StackName}-PrivateSubnet01ID" + PrivateSubnet02ID: + Description: The ID of Private Subnet Availability Zone 2 in ZMS VPC + Value: !Ref PrivateSubnet02 + Export: + Name: !Sub "${AWS::StackName}-PrivateSubnet02ID" + LoadBalancerName : + Description: The name of ZMS Load Balancer + Value: !Ref ZMSLoadBalancer + Export: + Name: !Sub "${AWS::StackName}-LoadBalancerName" + ServerSecurityGroupID: + Description: TThe ID of ZMS Server security group + Value: !Ref ZMSServerSecurityGroup + Export: + Name: !Sub "${AWS::StackName}-ServerSecurityGroupID" + diff --git a/aws-setup/zms-setup/cloud-formation/athens-zms-aws-roles-setup.yaml b/aws-setup/zms-setup/cloud-formation/athens-zms-aws-roles-setup.yaml new file mode 100755 index 00000000000..8e74080f27e --- /dev/null +++ b/aws-setup/zms-setup/cloud-formation/athens-zms-aws-roles-setup.yaml @@ -0,0 +1,52 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: Roles needed for athens ZMS setup +Parameters: + AthensServiceRole: + Type: String + Description: The Athens role name for the service + Default: athenz.zms-service +Resources: + AthensServiceEC2Role: + Type: "AWS::IAM::Role" + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - + Effect: "Allow" + Principal: + Service: + - "ec2.amazonaws.com" + Action: + - "sts:AssumeRole" + Policies: + - + PolicyName: !Sub ${AthensServiceRole}.policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + - logs:DescribeLogStreams + - logs:DescribeLogGroups + Resource: "arn:aws:logs:*:*:*" + - Effect: "Allow" + Action: + - rds-db:connect + Resource: + - !Sub arn:aws:rds-db:us-west-2:${AWS::AccountId}:dbuser:*/zms + - !Sub arn:aws:rds-db:us-east-1:${AWS::AccountId}:dbuser:*/zms + - Effect: "Allow" + Action: "ec2:DescribeTags" + Resource: "*" + Path: / + RoleName: !Ref AthensServiceRole + AthensEc2InstanceProfile: + Type: "AWS::IAM::InstanceProfile" + Properties: + Roles: + - !Ref AthensServiceEC2Role + InstanceProfileName: !Ref AthensServiceRole \ No newline at end of file diff --git a/aws-setup/zms-setup/cloud-formation/athenz-zms-aws-instance-deployment.yaml b/aws-setup/zms-setup/cloud-formation/athenz-zms-aws-instance-deployment.yaml new file mode 100755 index 00000000000..b27f167087a --- /dev/null +++ b/aws-setup/zms-setup/cloud-formation/athenz-zms-aws-instance-deployment.yaml @@ -0,0 +1,178 @@ +Description: 'Athenz ZMS standard 2 Availabilty zone instance deployment template' +Parameters: + ServiceRole: + Type: String + Description: The ZMS Service IAM Role Name + Default: "athenz.zms-service" + KeyName: + Type: String + Description: The EC2 key pair for the instance + ServiceName: + Type: String + Description: The service name for ZMS server + Default: "zms" + ResourceStackName: + Type: String + Description: Name of Stack used to create AWS Resources + Environment: + Type: String + Description: The environment ZMS is running in + AllowedValues: + - prod + - stage + - dev + ImageId: + Type: AWS::EC2::Image::Id + Description: "The ImageId to use for the EC2 instance. Should be a format like ami-XXXXXXXX" + AutoScalingMinSize: + Type: String + Description: The minimum instances for auto scaling + Default: "2" + AutoScalingMaxSize: + Type: String + Description: The maximum instances for auto scaling + Default: "4" + AutoScalingDesiredCapacity: + Type: String + Description: The desired number of instances + Default: "2" + EbsOptimized: + Type: String + Description: If EBS is to be optimized + AllowedValues: + - "true" + - "false" + Default: "false" + Ec2InstanceType: + Type: String + Description: The instance type to use for the host + Default: t2.large + AllowedValues: + - t2.nano + - t2.micro + - t2.small + - t2.medium + - t2.large + - t2.xlarge + - t2.2xlarge + - m4.large + - m4.xlarge + - m4.2xlarge + - m4.4xlarge + - m4.10xlarge + - m4.16xlarge + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + - m5.12xlarge + - m5.24xlarge + - m5d.large + - m5d.xlarge + - m5d.2xlarge + - m5d.4xlarge + - m5d.12xlarge + - m5d.24xlarge + EbsVolumeType: + Type: String + Description: The value for EBS Volume type in Block Device Mappings for Launch Configuration + Default: "gp2" + EbsVolumeSize: + Type: Number + Description: The value for EBS Volume size Block Device Mappings for Launch Configuration + Default: "50" +Resources: + ZMSEC2AutoScalingGroup: + Type: 'AWS::AutoScaling::AutoScalingGroup' + Properties: + LaunchConfigurationName: !Ref ZMSLaunchConfig + LoadBalancerNames: + - Fn::ImportValue: !Sub "${ResourceStackName}-LoadBalancerName" + MaxSize: !Ref AutoScalingMaxSize + MinSize: !Ref AutoScalingMinSize + Cooldown: 300 + VPCZoneIdentifier: + - Fn::ImportValue: !Sub "${ResourceStackName}-PrivateSubnet01ID" + - Fn::ImportValue: !Sub "${ResourceStackName}-PrivateSubnet02ID" + DesiredCapacity: !Ref AutoScalingDesiredCapacity + HealthCheckGracePeriod: 900 + HealthCheckType: ELB + Tags: + - Key: Name + Value: !Sub ${Environment}-asg-${ServiceName}-${AWS::Region} + PropagateAtLaunch: true + - Key: Environment + Value: !Ref Environment + PropagateAtLaunch: true + - Key: Stack + Value: !Ref AWS::StackName + PropagateAtLaunch: true + ZMSEC2IncreaseGroupSizeScalingPolicy: + Type: "AWS::AutoScaling::ScalingPolicy" + Properties: + AdjustmentType: ChangeInCapacity + AutoScalingGroupName: !Ref ZMSEC2AutoScalingGroup + Cooldown: 180 + ScalingAdjustment: 1 + CPUAlarmHigh: + Type: AWS::CloudWatch::Alarm + Properties: + EvaluationPeriods: '5' + Statistic: Average + Threshold: '50' + Unit: Percent + AlarmDescription: Alarm if CPU too high or metric disappears indicating instance + is down + Period: '60' + AlarmActions: + - Ref: ZMSEC2IncreaseGroupSizeScalingPolicy + Namespace: AWS/EC2 + Dimensions: + - Name: AutoScalingGroupName + Value: + Ref: ZMSEC2AutoScalingGroup + ComparisonOperator: GreaterThanThreshold + MetricName: CPUUtilization + ZMSEC2DecreaseGroupSizeScalingPolicy: + Type: "AWS::AutoScaling::ScalingPolicy" + Properties: + AdjustmentType: ChangeInCapacity + AutoScalingGroupName: !Ref ZMSEC2AutoScalingGroup + Cooldown: 300 + ScalingAdjustment: -1 + CPUAlarmLow: + Type: AWS::CloudWatch::Alarm + Properties: + EvaluationPeriods: '5' + Statistic: Average + Threshold: '20' + Unit: Percent + AlarmDescription: Alarm if CPU too low + Period: '60' + AlarmActions: + - Ref: ZMSEC2DecreaseGroupSizeScalingPolicy + Namespace: AWS/EC2 + Dimensions: + - Name: AutoScalingGroupName + Value: + Ref: ZMSEC2AutoScalingGroup + ComparisonOperator: LessThanThreshold + MetricName: CPUUtilization + ZMSLaunchConfig: + Type: 'AWS::AutoScaling::LaunchConfiguration' + Properties: + AssociatePublicIpAddress: false + IamInstanceProfile: !Sub arn:aws:iam::${AWS::AccountId}:instance-profile/${ServiceRole} + ImageId: !Ref ImageId + KeyName: !Ref KeyName + InstanceType: !Ref Ec2InstanceType + EbsOptimized: !Ref EbsOptimized + SecurityGroups: + - Fn::ImportValue: !Sub "${ResourceStackName}-ServerSecurityGroupID" + BlockDeviceMappings: + - DeviceName: "/dev/sda1" + Ebs: + VolumeSize: !Ref EbsVolumeSize + VolumeType: !Ref EbsVolumeType + DeleteOnTermination: true + InstanceMonitoring: true \ No newline at end of file diff --git a/aws-setup/zms-setup/cloud-formation/athenz-zms-aws-rds-setup.yaml b/aws-setup/zms-setup/cloud-formation/athenz-zms-aws-rds-setup.yaml new file mode 100755 index 00000000000..e822a6306fa --- /dev/null +++ b/aws-setup/zms-setup/cloud-formation/athenz-zms-aws-rds-setup.yaml @@ -0,0 +1,225 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: 'Athenz ZMS standard 2 Availabilty zone RDS configuration template' +Parameters: + ServiceName: + Type: String + Description: The service name for ZMS server + Default: "zms" + GroupName: + Type: String + Description: The Athens domain for the account + Default: "Athenz" + ResourceStackName: + Type: String + Description: Name of Stack used to create AWS Resources + Environment: + Type: String + Description: The environment ZMS is running in + AllowedValues: + - prod + - stage + - dev + DatabaseName: + Type: String + Description: Database Name + Default: "zmsstore" + MinLength: "1" + MaxLength: "64" + AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*" + ConstraintDescription: "must begin with a letter and contain only alphanumeric characters." + DatabaseUsername: + NoEcho: "true" + Type: String + Description: Database Username + Default: "dbuser" + MinLength: "1" + MaxLength: "16" + AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*" + ConstraintDescription: "must begin with a letter and contain only alphanumeric characters." + DatabasePassword: + NoEcho: "true" + Type: String + Description: Database Password + Default: "dbpasswd" + MinLength: "1" + MaxLength: "41" + AllowedPattern: "[a-zA-Z0-9]+" + ConstraintDescription: "must contain only alphanumeric characters." + DatabaseInstanceClass: + Type: String + Description: "The database instance type" + Default: "db.t2.medium" + AllowedValues: + - db.t1.micro + - db.t1.micro + - db.t1.micro + - db.t1.micro + - db.m1.small + - db.m1.medium + - db.m1.large + - db.m1.xlarge + - db.m2.xlarge + - db.m2.2xlarge + - db.m2.4xlarge + - db.m3.medium + - db.m3.large + - db.m3.xlarge + - db.m3.2xlarge + - db.m4.large + - db.m4.xlarge + - db.m4.2xlarge + - db.m4.4xlarge + - db.m4.10xlarge + - db.r3.large + - db.r3.xlarge + - db.r3.2xlarge + - db.r3.4xlarge + - db.r3.8xlarge + - db.m2.xlarge + - db.m2.2xlarge + - db.m2.4xlarge + - db.cr1.8xlarge + - db.t2.micro + - db.t2.small + - db.t2.medium + - db.t2.large" + ConstraintDescription: "must select a valid database instance type." + EncryptDatabaseStorage: + Type: String + Description: Encrypt database storage + AllowedValues: + - "true" + - "false" + Default: "true" + Route53HostedZoneName: + Type: String + Description: The hosted zone name to place a CNAME entry for. Must end with a period. Empty string means do not create one. + Route53DatabaseRecordName: + Type: String + Description: The hosted records to be added +Conditions: + CreateDNSRecordSet: !Not [!Equals [ !Ref Route53HostedZoneName, '']] + EnableDatabaseEncryption: !Equals [ !Ref EncryptDatabaseStorage , true] + +Resources: + DatabaseSubnetGroup: + Type: AWS::RDS::DBSubnetGroup + Properties: + DBSubnetGroupDescription: CloudFormation managed DB subnet group. + DBSubnetGroupName: !Sub ${Environment}-${ServiceName}-db-subnet + SubnetIds: + - Fn::ImportValue: !Sub "${ResourceStackName}-PrivateSubnet01ID" + - Fn::ImportValue: !Sub "${ResourceStackName}-PrivateSubnet02ID" + DatabaseCluster: + Type: AWS::RDS::DBCluster + Properties: + Engine: aurora + DatabaseName: !Ref "DatabaseName" + MasterUsername: !Ref "DatabaseUsername" + MasterUserPassword: !Ref "DatabasePassword" + BackupRetentionPeriod: 7 + PreferredBackupWindow: 01:00-02:00 + PreferredMaintenanceWindow: mon:03:00-mon:04:00 + DBSubnetGroupName: !Ref "DatabaseSubnetGroup" + VpcSecurityGroupIds: [!Ref "ZMSDBVPCSecurityGroup"] + StorageEncrypted: !Ref EncryptDatabaseStorage + KmsKeyId: !If [EnableDatabaseEncryption, !GetAtt DatabaseEncryptionKey.Arn, !Ref "AWS::NoValue"] + ZMSDBVPCSecurityGroup: + Type: "AWS::EC2::SecurityGroup" + Properties: + GroupName: !Sub ${GroupName}-${Environment}-rds-sg-${ServiceName}-${AWS::Region} + GroupDescription: 'ZMS public db security group' + SecurityGroupIngress: + - IpProtocol: TCP + FromPort: '3306' + ToPort: '3306' + CidrIp: '10.0.0.0/20' + VpcId: + Fn::ImportValue: !Sub "${ResourceStackName}-VPCID" + Tags: + - Key: Name + Value: !Sub ${Environment}-rds-sg-${ServiceName}-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + DatabaseEncryptionKey: + Type: 'AWS::KMS::Key' + Condition: EnableDatabaseEncryption + Properties: + Description: "KMS key for database encryption" + EnableKeyRotation: true + Enabled: true + KeyPolicy: + Version: 2012-10-17 + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: !Sub arn:aws:iam::${AWS::AccountId}:root + Action: 'kms:*' + Resource: '*' + Tags: + - Key: Name + Value: !Sub ${DatabaseName}-${AWS::Region}-encryption-key + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + DatabaseEncryptionKeyAlias: + Type: AWS::KMS::Alias + Condition: EnableDatabaseEncryption + Properties: + AliasName: !Sub alias/${DatabaseName}-${AWS::Region}-encryption-key + TargetKeyId: !Ref DatabaseEncryptionKey + DatabasePrimaryInstance: + Type: AWS::RDS::DBInstance + Properties: + Engine: aurora + DBClusterIdentifier: !Ref "DatabaseCluster" + DBInstanceClass: !Ref DatabaseInstanceClass + DBSubnetGroupName: !Ref "DatabaseSubnetGroup" + PubliclyAccessible: "false" + DBInstanceIdentifier: !Ref "DatabaseName" + Tags: + - Key: Name + Value: !Ref "DatabaseName" + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + DatabaseReplicaInstance: + Type: AWS::RDS::DBInstance + Properties: + Engine: aurora + DBClusterIdentifier: !Ref "DatabaseCluster" + DBInstanceClass: !Ref DatabaseInstanceClass + DBSubnetGroupName: !Ref "DatabaseSubnetGroup" + PubliclyAccessible: "false" + DBInstanceIdentifier: !Sub ${DatabaseName}-${AWS::Region} + Tags: + - Key: Name + Value: !Sub ${DatabaseName}-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + ZMSDatabaseRecordSet: + Type: AWS::Route53::RecordSet + Condition: CreateDNSRecordSet + Properties: + Comment: CNAME record for the ZMS DB. + HostedZoneName: !Ref Route53HostedZoneName + Name: !Ref Route53DatabaseRecordName + TTL: 60 + Type: CNAME + ResourceRecords: + - !GetAtt DatabaseCluster.Endpoint.Address +Outputs: + DatabasePrimaryInstanceEndpoint: + Description: Endpoint for primary database + Value: !GetAtt DatabasePrimaryInstance.Endpoint.Address + DatabaseReplicaInstanceEndpoint: + Description: Endpoint for primary database + Value: !GetAtt DatabaseReplicaInstance.Endpoint.Address \ No newline at end of file diff --git a/aws-setup/zms-setup/packer/aws/packer.json b/aws-setup/zms-setup/packer/aws/packer.json new file mode 100755 index 00000000000..2a72f89f0ec --- /dev/null +++ b/aws-setup/zms-setup/packer/aws/packer.json @@ -0,0 +1,105 @@ +{ + "variables": { + "subnet_id":"subnet-xxxxxxxxx", + "vpc_id": "vpc-xxxxxxxxxxxxxx", + "aws_region": "{{env `AWS_REGION`}}", + "aws_ami_name": "zms-aws-cd-image", + "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}", + "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}", + "aws_session_token": "{{env `AWS_SESSION_TOKEN`}}", + "ssh_keypair_name":"keypair-name", + "ssh_private_key_file":"path to ssh key file", + "source_ami": "ami-02c71d7a" + }, + + "builders": [{ + "access_key": "{{user `aws_access_key`}}", + "secret_key": "{{user `aws_secret_key`}}", + "token": "{{user `aws_session_token`}}", + "name": "amazon-ebs", + "ssh_username": "centos", + "ssh_keypair_name":"{{user `ssh_keypair_name`}}", + "ssh_private_key_file":"{{user `ssh_private_key_file`}}", + "type": "amazon-ebs", + "region": "{{user `aws_region`}}", + "source_ami": "{{user `source_ami`}}", + "ami_block_device_mappings": [ + { + "device_name": "/dev/sda1", + "volume_type": "gp2", + "volume_size": 50, + "encrypted": true, + "delete_on_termination": true + } + ], + "instance_type": "t2.micro", + "ami_name": "{{user `aws_ami_name`}}", + "ami_description": "ZMS Image for cloud formation", + "associate_public_ip_address": "true", + "subnet_id": "{{ user `subnet_id` }}", + "vpc_id": "{{ user `vpc_id` }}" + }], + + "provisioners": [ + { + "type": "shell", + "execute_command": "echo {{user `ssh_username`}} | {{ .Vars }} sudo -E -S sh '{{ .Path }}'", + "inline": [ + "mkdir -p /opt", + "chmod a+w /opt" + ] + }, + { + "type": "shell", + "execute_command": "echo {{user `ssh_username`}} | {{ .Vars }} sudo -E -S sh '{{ .Path }}'", + "inline": [ + "mkdir -p /opt/zms/tars", + "mkdir -p /opt/zms/jars", + "mkdir -p /opt/zms/logs", + "mkdir -p /opt/zms/webapps", + "mkdir -p /opt/zms/etc", + "mkdir -p /opt/zms/bin", + "mkdir -p /opt/zms/temp", + "mkdir -p /opt/zms/service", + "mkdir -p /opt/zms/conf", + "mkdir -p /opt/zms/conf/zms_server", + "mkdir /var/log/zms_server", + "chmod 777 /opt/zms -R" + ] + }, + { + "type": "file", + "source": "build/bin/", + "destination": "/opt/zms/bin/" + }, + { + "type": "file", + "source": "build/conf/", + "destination": "/opt/zms/conf/" + }, + { + "type": "file", + "source": "build/service/", + "destination": "/opt/zms/service" + }, + { + "type": "file", + "source": "tars/", + "destination": "/opt/zms/tars/" + }, + { + "type": "shell", + "execute_command": "echo {{user `ssh_username`}} | {{ .Vars }} sudo -E -S sh '{{ .Path }}'", + "inline": [ + "ls -ltr /opt/" + ] + }, + { + "type": "shell", + "scripts": [ + "packer/scripts/setup.sh" + ], + "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo -E '{{ .Path }}'" + } + ] +} diff --git a/aws-setup/zms-setup/packer/scripts/setup.sh b/aws-setup/zms-setup/packer/scripts/setup.sh new file mode 100755 index 00000000000..e6f380c0871 --- /dev/null +++ b/aws-setup/zms-setup/packer/scripts/setup.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +set -xe + +# install epel + +sudo yum -y install epel-release +sudo yum repolist + +# install aws_cli + +echo "install aws" +sudo yum -y install python-pip +sudo pip install awscli +aws --version + +# install openjdk + +sudo yum -y install java-1.8.0-openjdk + +# setup our athenz group and user + +sudo groupadd athenz +sudo useradd -g athenz athenz-zms + +# Copying jars, war and webdefault.xml files +sudo tar -xzf /opt/zms/tars/athenz-zms-bin.tar.gz -C /opt/zms/tars/ +sudo ls -ltr /opt/zms/tars/ +sudo cp -r /opt/zms/tars/athenz-zms/lib/jars/ /opt/zms/ +sudo cp /opt/zms/tars/athenz-zms/etc/webdefault.xml /opt/zms/etc/ +sudo cp /opt/zms/tars/athenz-zms/webapps/zms.war /opt/zms/webapps/ +sudo cp /opt/zms/tars/athenz-zms/conf/zms_server/authorized_services.json /opt/zms/conf/zms_server/authorized_services.json +sudo cp /opt/zms/tars/athenz-zms/conf/zms_server/solution_templates.json /opt/zms/conf/zms_server/solution_templates.json +sudo cp -r /opt/zms/tars/athenz-zms/bin/linux/ /opt/zms/bin/ + +# setup our zms service + +sudo mkdir /etc/zms +sudo cp /opt/zms/service/zms.service /etc/zms/zms.service +sudo systemctl enable /etc/zms/zms.service +sudo cp /opt/zms/conf/zms-user /etc/sudoers.d/ + +#set up aws logs + +curl https://s3.amazonaws.com//aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -o /opt/zms/logs/awslogs-agent-setup.py + +# make sure all files are owned by our user/group + +sudo chown -R athenz-zms:athenz /opt/zms diff --git a/aws-setup/zts-setup/build/bin/athenz_conf.sh b/aws-setup/zts-setup/build/bin/athenz_conf.sh new file mode 100755 index 00000000000..50b4a37c1c4 --- /dev/null +++ b/aws-setup/zts-setup/build/bin/athenz_conf.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +############# +# Usage: athenz_conf.sh [outputFile] [zts key bucket path] [zts url] [zms key bucket path] [zms url] +# Generates Athenz conf file +############### + +displayUsage() { + echo "athenz_conf.sh [outputFile] [ztsDataBucketName] [ztsUrl] [zmsUrl]"; + echo 'athenz_conf.sh ./output.json athenz-zts-data-us-west-2 https://zts.athenz.com:4443/ https://zms.athenz.com:4443/'; +} + +if [ $# -ne 4 ] +then + displayUsage + exit 1 +fi + +zms_public_key_file=zms_service_x509_key_public.pem +zts_public_key_file=zts_service_x509_key_public.pem + +outputFile=$1 +ztsDataBucketName=$2 +ztsUrl=$3 +zmsUrl=$4 + +# download CA certs from S3 bucket and store locally in temp directory +aws s3 cp s3://$ztsDataBucketName/$zts_public_key_file /tmp/zts_pub_key +aws s3 cp s3://$ztsDataBucketName/$zms_public_key_file /tmp/zms_pub_key + +sudo /opt/zts/bin/athenz-conf-aws -z $zmsUrl -t $ztsUrl -k /tmp/zms_pub_key -e /tmp/zts_pub_key -o $outputFile diff --git a/aws-setup/zts-setup/build/bin/aws_config.sh b/aws-setup/zts-setup/build/bin/aws_config.sh new file mode 100755 index 00000000000..0ab33023c9a --- /dev/null +++ b/aws-setup/zts-setup/build/bin/aws_config.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +aws_config_dir="$HOME/.aws" + +if [ -z "$HOME" ]; then + aws_config_dir="/athenz-zts/.aws" +fi + +echo "Configuring aws config in $aws_config_dir" + +if [ ! -d "$aws_config_dir" ]; then + mkdir $aws_config_dir +fi + +aws_config="[default]\nregion=$REGION" +echo -e $aws_config > $aws_config_dir/config diff --git a/aws-setup/zts-setup/build/bin/aws_init.sh b/aws-setup/zts-setup/build/bin/aws_init.sh new file mode 100755 index 00000000000..3d6f34ba4bb --- /dev/null +++ b/aws-setup/zts-setup/build/bin/aws_init.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Exposes bucket names based on account and region +# ENV +# ZTS_DATA_BUCKET_NAME +# ZTS_DOMAIN_BUCKET_NAME +# ZTS_AUDIT_LOG_BUCKET_NAME +# CERTSIGN_BUCKET_NAME +# REGION + +set -e + +export REGION=`curl http://169.254.169.254/latest/dynamic/instance-identity/document|grep region|awk -F\" '{print $4}'` +export ENV="dev" + + +export ZTS_DATA_BUCKET_NAME="athenz-zts-data-bucket-name" +export ZTS_AUDIT_LOG_BUCKET_NAME="athenz-audit-log-bucket-name" +export ZTS_URL="https://zts.url:4443" +export ZMS_URL="https://zms.url:4443" +export RDS_MASTER="zts-rds-databasecluster-endpoint" +export ZTS_TRUST_STORE_PATH="/opt/zts/conf/zts_truststore.jks" +export TRUST_STORE_PATH="/opt/zts/conf/zts_java_truststore.jks" +export KEY_STORE_PATH="/opt/zts/conf/zts_keystore.pkcs12" +export JDK_CA_CERTS_PATH="/etc/alternatives/jre_1.8.0_openjdk/lib/security/cacerts" +export JDK_CA_CERTS_PWD="changeit" +export ATHENZ_CONF_PATH="/opt/zts/conf/athenz.conf" +export DATASTORE_NAME="zts_store" \ No newline at end of file diff --git a/aws-setup/zts-setup/build/bin/aws_java_truststore_gen.sh b/aws-setup/zts-setup/build/bin/aws_java_truststore_gen.sh new file mode 100755 index 00000000000..a2b45c110ad --- /dev/null +++ b/aws-setup/zts-setup/build/bin/aws_java_truststore_gen.sh @@ -0,0 +1,64 @@ +#!/bin/bash +############# +# Usage: aws_java_truststore_gen.sh [jdk-ca-certs-path] [jdk-ca-certs-pwd] [bucket name] [trust store path] +# Downloads CA certs from S3 bucket. Creates pkcs12 truststore for jetty. +# Check for generated truststore: openssl pkcs12 -info -in /opt/zts/conf/ca.pkcs12 +############### + +display_usage() { + echo "aws_java_truststore_gen.sh [jdk-ca-certs-path] [jdk-ca-certs-pwd] [bucket name] [trust store path]"; + echo "example: aws_java_truststore_gen.sh /opt/jvm/cacerts changeit oath-aws-athenz-sys-auth-certsign-us-west-2 /opt/zts/conf/ca.pkcs12" +} + +cleanup() { + rm -f /tmp/service_rds_ca_certs + rm -f split_cacert-* +} + +if [ $# -ne 4 ] +then + display_usage + exit 1 +fi + +cleanup + +# define our S3 bucket filenames. we'll be using the same names +# when we store files locally + +rds_ca_certs=service_rds_ca_certs +zms_ca_certs=zms_service_x509_ca_certs + +jdk_ca_certs_path=$1 +jdk_ca_certs_pwd=$2 +bucket_name=$3 +trust_store_path=$4 + +# download RDS CA certs from s3 bucket +# aws s3 client will automatically decrypt the data + +aws s3 cp s3://$bucket_name/$rds_ca_certs /tmp/$rds_ca_certs +aws s3 cp s3://$bucket_name/$zms_ca_certs /tmp/$zms_ca_certs + +# first copy the jdk ca certs into our given filename + +cp $jdk_ca_certs_path $trust_store_path +rc=$?; if [[ $rc != 0 ]]; then cleanup; exit $rc; fi +chmod u+w $trust_store_path + +# split the CA certs and add them to the truststore + +csplit -f split_cacert- -s -z /tmp/$rds_ca_certs '/^-----BEGIN CERTIFICATE-----/' {*} +CERT_FILES=split_cacert-* +for file in $CERT_FILES +do + echo "Processing $file file..." + keytool -import -noprompt -alias $file -keystore $trust_store_path -file $file -storepass $jdk_ca_certs_pwd + rc=$?; if [[ $rc != 0 ]]; then cleanup; exit $rc; fi +done + +keytool -import -noprompt -alias $zms_ca_certs -keystore $trust_store_path -file /tmp/$zms_ca_certs -storepass $jdk_ca_certs_pwd + +cleanup + +echo "successfully generated trust store" diff --git a/aws-setup/zts-setup/build/bin/aws_zts_keystore_gen.sh b/aws-setup/zts-setup/build/bin/aws_zts_keystore_gen.sh new file mode 100755 index 00000000000..618aa7ac4ee --- /dev/null +++ b/aws-setup/zts-setup/build/bin/aws_zts_keystore_gen.sh @@ -0,0 +1,62 @@ +#!/bin/bash +############# +# Usage: aws_zts_keystore_gen.sh [bucket name] [key store path] +# Downloads encrypted server.key and server.cert from private S3 bucket. +# Decrypts and creates pkcs12 keystore for jetty. +# Assumes that this script runs on an instance with a role that has policy +# set to allow kms decrypt and read access to private S3 bucket. +# Check for generated keystore: openssl pkcs12 -info -in jetty.pkcs12 +############### + +display_usage() { + echo "aws_zts_keystore_gen.sh [bucket name] [key store path]"; + echo "example: aws_zts_keystore_gen.sh oath-aws-athenz-sys-auth-zts-prod-data-us-west-2 jetty.pkcs12" +} + +cleanup() { + rm -f /tmp/service_x509_* +} + +if [ $# -ne 2 ] +then + display_usage + exit 1 +fi + +cleanup + +# define our S3 bucket filenames. we'll be using the same names +# when we store files locally + +key_file=service_x509_key +cert_file=service_x509_cert +pwd_file=service_x509_store_pwd + +bucket_name=$1 +key_store_path=$2 + +# download server cert and key from private s3 bucket +# aws s3 client will automatically decrypt the data + +aws s3 cp s3://$bucket_name/$key_file /tmp/$key_file +aws s3 cp s3://$bucket_name/$cert_file /tmp/$cert_file + +# extract the password the keystore + +aws s3 cp s3://$bucket_name/$pwd_file /tmp/$pwd_file +key_store_pass=`cat /tmp/$pwd_file` + +# generate pkcs12 keystore using openssl + +openssl pkcs12 -export -inkey /tmp/$key_file -in /tmp/$cert_file -out $key_store_path -password pass:$key_store_pass -noiter -nomaciter +openssl_status=$? + +cleanup + +if [ ! $openssl_status -eq 0 ]; then + echo "failed to generate key store" + exit 1 +fi + +echo "successfully generated key store" + diff --git a/aws-setup/zts-setup/build/bin/aws_zts_truststore_gen.sh b/aws-setup/zts-setup/build/bin/aws_zts_truststore_gen.sh new file mode 100755 index 00000000000..4637b7d4ca7 --- /dev/null +++ b/aws-setup/zts-setup/build/bin/aws_zts_truststore_gen.sh @@ -0,0 +1,58 @@ +#!/bin/bash +############# +# Usage: aws_zts_truststore_gen.sh [bucket name] [trust store path] +# Downloads CA certs from S3 bucket. Creates pkcs12 truststore for jetty. +# Check for generated truststore: openssl pkcs12 -info -in /opt/zts/conf/ca.pkcs12 +############### + +display_usage() { + echo "aws_zts_truststore_gen.sh [bucket name] [trust store path]"; + echo "example: aws_zts_truststore_gen.sh oath-aws-athenz-sys-auth-certsign-us-west-2 /opt/zts/conf/ca.pkcs12" +} + +cleanup() { + rm -f /tmp/service_x509_ca_certs + rm -f split_cacert-* +} + +if [ $# -ne 2 ] +then + display_usage + exit 1 +fi + +cleanup + +# define our S3 bucket filenames. we'll be using the same names +# when we store files locally + +ca_certs_file=service_x509_ca_certs +pwd_file=service_x509_store_pwd + +bucket_name=$1 +trust_store_path=$2 + +# download CA certs from s3 bucket +# aws s3 client will automatically decrypt the data + +aws s3 cp s3://$bucket_name/$ca_certs_file /tmp/$ca_certs_file + +# extract the password the truststore + +aws s3 cp s3://$bucket_name/$pwd_file /tmp/$pwd_file +trust_store_pass=`cat /tmp/$pwd_file` + +# split the CA certs and add them to the truststore + +csplit -f split_cacert- -s -z /tmp/$ca_certs_file '/^-----BEGIN CERTIFICATE-----/' {*} +CERT_FILES=split_cacert-* +for file in $CERT_FILES +do + echo "Processing $file file..." + keytool -import -noprompt -alias $file -keystore $trust_store_path -file $file -storepass $trust_store_pass + rc=$?; if [[ $rc != 0 ]]; then cleanup; exit $rc; fi +done + +cleanup + +echo "successfully generated trust store" diff --git a/aws-setup/zts-setup/build/bin/initialize_zts.sh b/aws-setup/zts-setup/build/bin/initialize_zts.sh new file mode 100755 index 00000000000..d2b5546a20d --- /dev/null +++ b/aws-setup/zts-setup/build/bin/initialize_zts.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Usage: initialize_zts.sh + +#Runs athenz.conf.sh to get athenz.conf file +# Runs aws_zts_truststore_gen.sh to get trust store +# Runs aws_java_truststore_gen.sh to get java trust store +# Runs aws_zts_keystore_gen.sh to generate key store. + + +set -e + +echo "creating aws config" +/opt/zts/bin/aws_config.sh + +echo "initializing aws cloudwatch log setup" +sudo python /opt/zts/logs/awslogs-agent-setup.py -n -r $REGION -c /opt/zts/conf/awslogs.conf + +cd /opt/zts/temp + +echo "generating athenz conf" +/opt/zts/bin/athenz_conf.sh $ATHENZ_CONF_PATH $ZTS_DATA_BUCKET_NAME $ZTS_URL $ZMS_URL + +echo "generating zts trust store /opt/zts/bin/aws_zts_truststore_gen.sh $ZTS_DATA_BUCKET_NAME $ZTS_TRUST_STORE_PATH" +rm -f $ZTS_TRUST_STORE_PATH +/opt/zts/bin/aws_zts_truststore_gen.sh $ZTS_DATA_BUCKET_NAME $ZTS_TRUST_STORE_PATH + +echo "generating java trust store /opt/zts/bin/aws_java_truststore_gen.sh $JDK_CA_CERTS_PATH $JDK_CA_CERTS_PWD $ZTS_DATA_BUCKET_NAME $TRUST_STORE_PATH" +rm -f $TRUST_STORE_PATH +/opt/zts/bin/aws_java_truststore_gen.sh $JDK_CA_CERTS_PATH $JDK_CA_CERTS_PWD $ZTS_DATA_BUCKET_NAME $TRUST_STORE_PATH + +echo "generating zts key store /opt/zts/bin/aws_zts_keystore_gen.sh $ZTS_DATA_BUCKET_NAME $KEY_STORE_PATH" +rm -f $KEY_STORE_PATH +/opt/zts/bin/aws_zts_keystore_gen.sh $ZTS_DATA_BUCKET_NAME $KEY_STORE_PATH + +# echo "Downloading self cert signer key" +# aws s3 cp s3://$bucket_name/self_cert_signer_key /opt/zts/conf/self_cert_signer_key + + diff --git a/aws-setup/zts-setup/build/bin/zts.sh b/aws-setup/zts-setup/build/bin/zts.sh new file mode 100755 index 00000000000..5015ead8783 --- /dev/null +++ b/aws-setup/zts-setup/build/bin/zts.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +set -e + +source /opt/zts/bin/aws_init.sh + +/opt/zts/bin/initialize_zts.sh +cd /opt/zts + +# setup our database cluster endpoint and other environment +# specific settings. us-west-2 is our primary region while +# us-east-1 is our backup read-only region + + + +JAVA_OPTS="-XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:+PrintGCDetails -Xloggc:/opt/zts/logs/gc.log" +JAVA_OPTS="${JAVA_OPTS} -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation" +JAVA_OPTS="${JAVA_OPTS} -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=4M" +JAVA_OPTS="${JAVA_OPTS} -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/zts/logs" + +java -server $JAVA_OPTS \ + -Dathenz.root_dir=/opt/zts \ + -Dathenz.zts.root_dir=/opt/zts \ + -Dlogback.configurationFile=/opt/zts/conf/logback.xml \ + -Dathenz.prop_file=/opt/zts/conf/athenz.properties \ + -Dathenz.zts.prop_file=/opt/zts/conf/zts.properties \ \ + -Dathenz.zts.cert_jdbc_store=jdbc:mysql://${RDS_MASTER}:3306/${DATASTORE_NAME} \ + -Dathenz.aws.zts.bucket_name=$ZTS_DATA_BUCKET_NAME \ + -Dathenz.zts.cert_jdbc_app_name=$ZTS_DATA_BUCKET_NAME \ + -Dathenz.zts.ssl_key_store_password_appname=$ZTS_DATA_BUCKET_NAME \ + -Dathenz.zts.ssl_trust_store_password_appname=$ZTS_DATA_BUCKET_NAME \ + -Dathenz.ssl_key_store_password_appname=$ZTS_DATA_BUCKET_NAME \ + -Dathenz.ssl_trust_store_password_appname=$ZTS_DATA_BUCKET_NAME \ + -Dathenz.zts.aws_region_name=$REGION \ + -Dathenz.zts.read_only_mode=false \ + -classpath ":/opt/zts/jars/*:" \ + com.yahoo.athenz.container.AthenzJettyContainer diff --git a/aws-setup/zts-setup/build/conf/athenz.properties b/aws-setup/zts-setup/build/conf/athenz.properties new file mode 100755 index 00000000000..b4cba25bbc1 --- /dev/null +++ b/aws-setup/zts-setup/build/conf/athenz.properties @@ -0,0 +1,148 @@ +# Athenz Jetty Container properties file. +# If there is a value specified in the commented property line, +# then it indicates the default value + +# The TLS port that Jetty will listen on for HTTPS connection +athenz.tls_port=4443 + +# The standard HTTP port for Jetty - disabled by default +athenz.port=0 + +# Port for requesting /status health check. If this setting is +# not specified, then the request will be handled by either http +# or https ports specified in the configuration. However, if this +# status port is specified and is different than the configured +# http and https ports, then /status endpoint will only be handled +# on this port and all other requests will be rejected. Similarly, +# /status endpoint will not be allowed on configured http/https +# ports. The status port will be either http or https depending +# which port is specified for data access. If both http and https +# ports are specified, https will be selected for the protocol. +athenz.status_port=8443 + +# Set the number of days before rotated access log files are deleted +athenz.access_log_retain_days=31 + +# Format of the access log filename +athenz.access_log_name=access.yyyy_MM_dd.log + +# If specified, the server will use SLF4J logger with the specified name +# to log events instead of using Jetty's NCSARequestLog class. +# The administrator then must configure the specified logger in the logback.xml +athenz.access_slf4j_logger= + +# Directory to store access log files +athenz.access_log_dir=/opt/zts/logs + +# Key Manager password +#athenz.ssl_key_manager_password= + +# The path to the keystore file that contains the server's certificate +athenz.ssl_key_store=/opt/zts/conf/zts_keystore.pkcs12 + +# Specifies the type for the keystore specified in the +# athenz.ssl_key_store property +athenz.ssl_key_store_type=PKCS12 + +# Password for the keystore specified in the athenz.ssl_key_store property +athenz.ssl_key_store_password=service_x509_store_pwd + +# The path to the trust store file that contains CA certificates +# trusted by this Jetty instance +athenz.ssl_trust_store=/opt/zts/conf/zts_truststore.jks + +# Specifies the type for the truststore specified in the +# athenz.ssl_trust_store property +athenz.ssl_trust_store_type=JKS + +# Password for the truststore specified in the athenz.ssl_trust_store property +athenz.ssl_trust_store_password=service_x509_store_pwd + +# Specifies whether or not for data requests the server +# would require TLS client authentication rather than +# just wanting it +athenz.ssl_need_client_auth=false + +# Private key store to extract the passwords defined for +# java keystore and truststore +athenz.private_keystore_factory_class=com.yahoo.athenz.auth.impl.aws.AwsPrivateKeyStoreFactory + +# Specifies the truststore used by java clients when communicating +# with other AWS services like S3 or RDS. This should be the +# JDK shipped truststore + AWS RDS CA truststore +javax.net.ssl.trustStore=/opt/zts/conf/zts_java_truststore.jks +javax.net.ssl.trustStorePassword=changeit + +# List of excluded cipher suites from TLS negotiation +#athenz.ssl_excluded_cipher_suites= + +# List of cipher suites supported for TLS negotiation +athenz.ssl_included_cipher_suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA + +# Comma separated list of excluded ssl protocols +#athenz.ssl_excluded_protocols=SSLv2,SSLv3 + +# Configure if client TLS renegotiation is allowed or not +athenz.ssl_renegotiation_allowed=false + +# Enable OCSP support +#athenz.ssl_enable_ocsp=false + +# In milliseconds how long that connector will be allowed to +# remain idle with no traffic before it is shutdown +athenz.http_idle_timeout=30000 + +# Boolean setting to specify whether or not the server should +# send the Server header in response +athenz.http_send_server_version=false + +# Boolean setting to specify whether or not the server should +# include the Date in HTTP headers +athenz.http_send_date_header=false + +# The size in bytes of the output buffer used to aggregate HTTP output +#athenz.http_output_buffer_size=32768 + +# The maximum allowed size in bytes for a HTTP request header +#athenz.http_reqeust_header_size=8192 + +# The maximum allowed size in bytes for a HTTP response header +#athenz.http_response_header_size=8192 + +# For HTTP access specifies the IP address/Host for service to listen on. +# This could be necessary, for example, if the system administrator +# wants some proxy server (e.g. ATS) to handle TLS traffic and configure +# Jetty to listen on 127.0.0.1 loopback address only for HTTP connections +# from that proxy server +#athenz.listen_host= + +# Boolean flag to indicate whether or not the container should honor +# the Keep Alive connection option or just connections right away +#athenz.keep_alive=false + +# Max number of threads Jetty is allowed to spawn to handle incoming requests +athenz.http_max_threads=1024 + +# Specify the FQDN/hostname of the server. This will bereported as part +# of the server banner notification in logs +#athenz.hostname= + +# Default home directory for embedded Jetty Deployer. The container will look +# for any servlets in the webapps subdirectory of the configured directory +athenz.jetty_home=/opt/zts + +# Boolean flag to enable debug log entries when deploying webapps +#athenz.debug=false + +# Comma separated liste of uris that are accessed by health check +# system. Used by the simple file based health check filter that +# returns 200/404 if the file exists or not +athenz.health_check_uri_list=/status + +# Directory name where the files specified in the athenz.health_check_uri_list +# setting are checked for +athenz.health_check_path=/opt/zts + +# Enable Proxy Protocol (used by HAProxy and environments such as Amazon Elastic Cloud) +# for the jetty container. +athenz.proxy_protocol=true diff --git a/aws-setup/zts-setup/build/conf/aws_public.crt b/aws-setup/zts-setup/build/conf/aws_public.crt new file mode 100755 index 00000000000..0ff9d47a900 --- /dev/null +++ b/aws-setup/zts-setup/build/conf/aws_public.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC7TCCAq0CCQCWukjZ5V4aZzAJBgcqhkjOOAQDMFwxCzAJBgNVBAYTAlVTMRkw +FwYDVQQIExBXYXNoaW5ndG9uIFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYD +VQQKExdBbWF6b24gV2ViIFNlcnZpY2VzIExMQzAeFw0xMjAxMDUxMjU2MTJaFw0z +ODAxMDUxMjU2MTJaMFwxCzAJBgNVBAYTAlVTMRkwFwYDVQQIExBXYXNoaW5ndG9u +IFN0YXRlMRAwDgYDVQQHEwdTZWF0dGxlMSAwHgYDVQQKExdBbWF6b24gV2ViIFNl +cnZpY2VzIExMQzCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQCjkvcS2bb1VQ4yt/5e +ih5OO6kK/n1Lzllr7D8ZwtQP8fOEpp5E2ng+D6Ud1Z1gYipr58Kj3nssSNpI6bX3 +VyIQzK7wLclnd/YozqNNmgIyZecN7EglK9ITHJLP+x8FtUpt3QbyYXJdmVMegN6P +hviYt5JH/nYl4hh3Pa1HJdskgQIVALVJ3ER11+Ko4tP6nwvHwh6+ERYRAoGBAI1j +k+tkqMVHuAFcvAGKocTgsjJem6/5qomzJuKDmbJNu9Qxw3rAotXau8Qe+MBcJl/U +hhy1KHVpCGl9fueQ2s6IL0CaO/buycU1CiYQk40KNHCcHfNiZbdlx1E9rpUp7bnF +lRa2v1ntMX3caRVDdbtPEWmdxSCYsYFDk4mZrOLBA4GEAAKBgEbmeve5f8LIE/Gf +MNmP9CM5eovQOGx5ho8WqD+aTebs+k2tn92BBPqeZqpWRa5P/+jrdKml1qx4llHW +MXrs3IgIb6+hUIB+S8dz8/mmO0bpr76RoZVCXYab2CZedFut7qc3WUH9+EUAH5mw +vSeDCOUMYQR7R9LINYwouHIziqQYMAkGByqGSM44BAMDLwAwLAIUWXBlk40xTwSw +7HX32MxXYruse9ACFBNGmdX2ZBrVNGrN9N2f6ROk0k9K + -----END CERTIFICATE----- \ No newline at end of file diff --git a/aws-setup/zts-setup/build/conf/awslogs.conf b/aws-setup/zts-setup/build/conf/awslogs.conf new file mode 100755 index 00000000000..3369074d776 --- /dev/null +++ b/aws-setup/zts-setup/build/conf/awslogs.conf @@ -0,0 +1,27 @@ +[general] +state_file = /var/awslogs/state/agent-state + +[syslog] +file = /var/log/messages +log_group_name = athenz-zts-service-syslog +log_stream_name = {instance_id} +datetime_format = %b %d %H:%M:%S + +[access] +file = /opt/zts/logs/access*.log +log_group_name = athenz-zts-service-access +log_stream_name = {instance_id} +datetime_format = %b %d %H:%M:%S + +[server] +file = /opt/zts/logs/zts_server/server*.log +log_group_name = athenz-zts-service-server +log_stream_name = {instance_id} +datetime_format = %b %d %H:%M:%S + +[gc] +file = /opt/zts/logs/gc.log.* +log_group_name = athenz-zts-service-gc +log_stream_name = {instance_id} +datetime_format = %b %d %H:%M:%S +== diff --git a/aws-setup/zts-setup/build/conf/logback.xml b/aws-setup/zts-setup/build/conf/logback.xml new file mode 100755 index 00000000000..502cf3a803a --- /dev/null +++ b/aws-setup/zts-setup/build/conf/logback.xml @@ -0,0 +1,49 @@ + + + + + + + + + ${LOG_DIR}/server.log + true + + + ${LOG_DIR}/server.%d.log + 7 + true + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg%n + + + + + + + ${LOG_DIR}/audit.log + true + + + ${LOG_DIR}/audit.%d.log + 30 + true + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg%n + + + + + + + + + + + + + diff --git a/aws-setup/zts-setup/build/conf/zts-user b/aws-setup/zts-setup/build/conf/zts-user new file mode 100755 index 00000000000..c4fa502900c --- /dev/null +++ b/aws-setup/zts-setup/build/conf/zts-user @@ -0,0 +1 @@ +athenz-zts ALL=(ALL) NOPASSWD: ALL \ No newline at end of file diff --git a/aws-setup/zts-setup/build/conf/zts.properties b/aws-setup/zts-setup/build/conf/zts.properties new file mode 100755 index 00000000000..24951b5ec84 --- /dev/null +++ b/aws-setup/zts-setup/build/conf/zts.properties @@ -0,0 +1,337 @@ +# Athenz ZTS Service properties file. +# If there is a value specified in the commented property line, +# then it indicates the default value + +# Specifies the user domain name for the current installation +#athenz.user_domain=user + +# Specifies the user domain alias name for the current installation +#athenz.user_domain_alias=yby + +# ZTS is running within AWS so enable features such as getting temporary +# credentials, etc. +athenz.zts.aws_enabled=true + +# If ZTS is running within AWS and we need to validate the host identity document +# before we issue a TLS certificate for a service identified by its IAM role, +# the server verifies that the instance was booted within the configured number +# of seconds +athenz.zts.aws_boot_time_offset=1800 + +# If ZTS is running within AWS, this setting specifies path a file that includes +# the AWS Public certificate that is needed to verify host identity documents +# provided by AWS. +athenz.zts.aws_public_cert=/opt/zts/conf/aws_public.crt + +# If ZTS is running within AWS, this setting specifies the DNS suffix +# that the AWS provider will use to validate all hostnames in the CSR +athenz.zts.aws_dns_suffix=aws.oath.cloud + +# Comma separated list of authority implementation classes to support +# authenticating principals in ZTS +# athenz.zts.authority_classes=com.yahoo.athenz.auth.oath.impl.CertificateOktaAuthority,com.yahoo.athenz.auth.impl.CertificateAuthority + +# If File Private Key store implementation is used in the Server, +# this setting specifies the path to the PEM encoded ZTS Server +# private key file (both RSA and EC privates keys are supported) +#athenz.auth.private_key_store.private_key= + +# If File Private Key store implementation is used in the Server, +# this setting specifies the key identifier for the private key +# configured by the athenz.auth.private_key_store.private_key +# property +#athenz.auth.private_key_store.private_key_id= + +# Key Manager password +#athenz.zts.ssl_key_manager_password= + +# The path to the keystore file that contains the client's private key +# and certificate. Currently this is only used by the HttpCertSigner +# class implementation. +athenz.zts.ssl_key_store=/opt/zts/conf/zts_keystore.pkcs12 + +# Specifies the type for the keystore specified in the +# athenz.zts.ssl_key_store property +athenz.zts.ssl_key_store_type=PKCS12 + +# Password for the keystore specified in the athenz.zts.ssl_key_store property +athenz.zts.ssl_key_store_password=service_x509_store_pwd + +# The path to the trust store file that contains CA certificates +# trusted by the http client running within this ZTS instance +athenz.zts.ssl_trust_store=/opt/zts/conf/zts_truststore.jks + +# Type for the truststore specified in the athenz.zts.ssl_trust_store property +athenz.zts.ssl_trust_store_type=JKS + +# Password for the truststore specified in the athenz.zts.ssl_trust_store property +athenz.zts.ssl_trust_store_password=service_x509_store_pwd + +# Specifies the location for the athenz.conf file used by the ZMS Client +# library to determine what ZMS server to contact to. +athenz.athenz_conf=/opt/zts/conf/athenz.conf + +# If specified, this setting overrides the ZMS Server url value for the +# ZMS Client as retrieved from the athenz.conf file +#athenz.zts.zms_url=https://test.athens.aws.oath.cloud:4443/ + +# SelfCertSignerFactory implementation - if this factory class is used +# is used for the CertSigner implementation (athenz.zts.cert_signer_factory_class +# property), this setting specifies the private key filename that is used to sign +# certificate requests. +# athenz.zts.self_signer_private_key_fname=/opt/zts/conf/self_cert_signer_key + +# SelfCertSignerFactory implementation - if this factory class is used +# is used for the CertSigner implementation (athenz.zts.cert_signer_factory_class +# property), this setting specifies the private key password that is used to sign +# certificate requests. +#athenz.zts.self_signer_private_key_password= + +# SelfCertSignerFactory implementation - if this factory class is used +# is used for the CertSigner implementation (athenz.zts.cert_signer_factory_class +# property), this setting specifies the dn for the CA certificate that ZTS +# will use +# athenz.zts.self_signer_cert_dn=C=US,ST=CA,L=Sunnyvale,O=Oath,OU=Athenz,CN=zts.aws.oath.cloud. + +# HttpCertSignerFactory implementation - if this factory class is used +# for the for the CertSigner implementation (athenz.zts.cert_signer_factory_class +# property), this setting specifies the base uri for the Certificate Signer Service +#athenz.zts.certsign_base_uri= + +# HttpCertSignerFactory implementation - if this factory class is used +# for the CertSigner implementation (athenz.zts.cert_signer_factory_class +# property), this setting specifies in seconds the connect timeout +#athenz.zts.certsign_connect_timeout=10 + +# HttpCertSignerFactory implementation - if this factory class is used +# for the CertSigner implementation (athenz.zts.cert_signer_factory_class +# property), this setting specifies in seconds the request timeout. +# We're setting the initial value to a small on so we know right away +# if our idle connection has been been closed by cert signer and we'll +# use our retry setting to retry with a max timout of 30 seconds. +#athenz.zts.certsign_request_timeout=5 + +# HttpCertSignerFactory implementation - if this factory class is used +# for the CertSigner implementation (athenz.zts.cert_signer_factory_class +# property), this setting specifies the number of times the request +# should be retried if it's not completed with the requested timeout value +#athenz.zts.certsign_retry_count=3 + +# Specifies the factory class that implements the Metrics interface +# used by the ZTS Server to report stats +athenz.zts.metric_factory_class=com.yahoo.athenz.common.metrics.impl.NoOpMetricFactory + +# Specifies the factory class that implements the AuditLoggerFactory +# interface used by the ZTS Server to log all changes to domain +# data for auditing purposes +athenz.zts.audit_logger_factory_class=com.yahoo.athenz.common.server.log.impl.DefaultAuditLoggerFactory + +# Specifies the factory class that implements the PrivateKeyStoreFactory +# interface used by the ZTS Server to get access to its host specific +# private key +athenz.zts.private_key_store_factory_class=com.yahoo.athenz.auth.impl.aws.AwsPrivateKeyStoreFactory + +# Specifies the factory class that implements CertSignerFactory +# interface used by the ZTS Server to sign any certificate requests +athenz.zts.cert_signer_factory_class=com.yahoo.athenz.zts.cert.impl.SelfCertSignerFactory + +# Specifies the factory class that implements ChangeLogStoreFactory +# interface used by the ZTS Server to retrieve the latest changes +# from the ZMS Server and save them locally +athenz.zts.change_log_store_factory_class=com.yahoo.athenz.zts.store.impl.ZMSChangeLogStoreFactory + +# Specifies the directory for storing zms domain json documents when +# ZMSFileChangeLogStoreFactory is configured for the change log factory +# class (athenz.zts.data_change_log_store_factory_class property) +athenz.zts.change_log_store_dir=/opt/zts/domains + + +# Boolean setting to force users to request role tokens for specific +# roles rather than for domain which will includes all the roles the +# given principal has access in that domain +#athenz.zts.least_privilege_principle=false + +# Specifies the maximum expiry timeout that a client can ask for when +# requesting a role token. If the client asks for a longer timeout, the +# server will automatically replace the value with this one +#athenz.zts.role_token_max_timeout=2592000 + +# Specifies the default expiry timeout for role tokens when the client +# does not specify any timeout parameters +#athenz.zts.role_token_default_timeout=7200 + +# Specifies the expiry timeout for signed policy documents that +# ZTS Server signs and returns to ZPU clients +#athenz.zts.signed_policy_timeout=604800 + +# Comma separated list of authorized proxy principals +#athenz.zts.authorized_proxy_users= + +# Specifies the service name that the ostk instance documents are +# signed with. +#athenz.zts.ostk_host_signer_service= + +# If the ZTS servlet is deployed along other servlets that may +# run on non-TLS ports, this setting forces that requests to +# ZTS are only accepted on secure TLS ports. +#athenz.zts.secure_requests_only=true + +# Comma separated list of hostname suffixes that providers +# are allowed to use for their verifiers +athenz.zts.provider_endpoints=athenz.cloud + +# Specifies timeout in seconds for NTokens issued by ZTS +# Server as part of the Instance bootstrap request +#athenz.zts.instance_token_timeout=86400 + +# Specifies in seconds how often to query ZMS Server for updates +# The default value is 60 seconds +#athenz.zts.zms_domain_update_timeout=60 + +# Specifies in seconds how often to query ZMS Server for the full +# list of domains to determine the deleted domains +# The default value is 3600 seconds +#athenz.zts.zms_domain_delete_timeout=3600 + +# JDBC URL where the ZTS Server will store certificate records for +# revocation checks +# jdbc:mysql://localhost:3306/zts - specifies MySQL instance +#athenz.zts.cert_jdbc_store= + +# If the jdbcstore is pointing to a MySQL server then this specifies +# the name of the user that has full access to the zts database +athenz.zts.cert_jdbc_user=athenz-zts + +# If the jdbcstore is pointing to a MySQL server then this specifies +# the password for the jdbc user that has been granted full access +# to the configured zts database +athenz.zts.cert_jdbc_password=db_user_data + +# Specifies the factory class for the certificate record factory +# class implementation +athenz.zts.cert_record_store_factory_class=com.yahoo.athenz.zts.cert.impl.JDBCCertRecordStoreFactory + +# If the athenz.zts.cert_record_store_factory_class property is using +# the aws rds mysql object store factory identified with +# com.yahoo.athenz.zts.store.impl.AWSObjectStoreFactory, then +# this setting specifies AWS RDS instance hostname. +# The database server must be initialized with the ZTS +# server schema. +# athenz.zts.aws_rds_master_instance= + +# If the athenz.zts.cert_record_store_factory_class property is using +# the aws rds mysql object store then this setting specifies +# the database user configured with IAM Role AWS authentication +# and full access to the zts store database +# athenz.zts.aws_rds_user=zts + +# If the athenz.zts.cert_record_store_factory_class property is using +# the aws rds mysql object store then this setting specifies +# the IMA role that has been enabled for authentication +# athenz.zts.aws_rds_iam_role=athenz.zts-service + +# If the athenz.zts.cert_record_store_factory_class property is using +# the aws rds mysql object store then this setting specifies +# the port number for the RDL database instance +# athenz.zts.aws_rds_master_port=3306 + +# If the athenz.zts.cert_record_store_factory_class property is using +# the aws rds mysql object store then this setting specifies +# the database engine used in rds +# athenz.zts.aws_rds_engine=mysql + +# If the athenz.zts.cert_record_store_factory_class property is using +# the aws rds mysql object store then this setting specifies +# the database name in rds +# athenz.zts.aws_rds_database=zts_store + +# If the athenz.zts.cert_record_store_factory_class property is using +# the aws rds mysql object store then this setting specifies +# in seconds how often to update the aws credentials for the IAM role +athenz.zts.aws_rds_creds_refresh_time=300 + +# The maximum number of seconds that the server should wait +# for the certificate store connection object to return its results +athenz.zts.cert_op_timeout=60 + +# When requesting TLS certificates for their corresponding NTokens, +# services must this dns suffix in their CSRs +athenz.zts.cert_dns_suffix=aws.oath.cloud + +# Kerberos Authority Service Principal +#athenz.auth.kerberos.service_principal= + +# Kerberos Authority location of keytab file +#athenz.auth.kerberos.keytab_location= + +# Kerberos Authority debug boolean state +#athenz.auth.kerberos.debug=false + +# Kerberos Authority - if there is a jaas.conf whose path is specified by +# the system property java.security.auth.login.config then this setting +# specifies the config section name to be used for the authority +#athenz.auth.kerberos.jaas_cfg_section= + +# Kerberos Authority - login callback handler class +#athenz.auth.kerberos.login_callback_handler_class= + +# Kerberos Authority - boolean flag whether or not to renew TGT +#athenz.auth.kerberos.renewTGT=true + +# Kerberos Authority - boolean flag whether or not using ticket cache +#athenz.auth.kerberos.use_ticket_cache=true + +# Kerberos Authority - file path for the ticket cache data +#athenz.auth.kerberos.ticket_cache_name= + +# Kerberos Authority - in milliseconds the login window time for re-logins +#athenz.auth.kerberos.login_window=60000 + +# Kerberos Authority - privileged action class name +#athenz.auth.kerberos.krb_privileged_action_class= + +# Kerberos Authority - the realm for kerberos users (this could be a realm +# that regular users (also authenticated as part of UserAuthority) are part of +#athenz.auth.kerberos.user_realm= + +# Kerberos Authority - the domain name for users that are only authenticated +# by this authority +#athenz.auth.kerberos.krb_user_domain=ygrid + +# Kerberos Authority - the realm name for users that are only authenticated +# by this authority +#athenz.auth.kerberos.krb_user_realm= + +# Comma separated list of URIs that require authentication according to the RDL +# but we want the server to make the authentication as optional. The URI can +# include regex values based on + character to match resource URIs +# for example, /zts/v1/domain/.+/service +athenz.zts.no_auth_uri_list=/zts/v1/status + +# Filename that includes list of IP address blocks that are +# authorized to carry out cert refresh operation for manually +# generated certs +#athenz.zts.cert_refresh_ip_fname=/opt/zts/conf/cert_refresh_ipblocks.json + +# Filename that includes list of IP address blocks that are +# authorized to carry out instance register operations +#athenz.zts.instance_cert_ip_fname=/opt/zts/conf/instance_cert_ipblocks.json + +# list of accepted client ids for Okta authority +#athenz.auth_core.cert_okta.client_ids_fname=/opt/zts/conf/client_map_ids.txt + +# okta authority url +#athenz.auth_core.cert_okta.url=https://oath.okta.com/oauth2/aus3veicdv5jKkozw1t7/ + +# zts service athenz private key path +#athenz.zts.service_private_key_path=/var/lib/sia/keys/athenz.zts.key.pem + +# zts service athenz certificate path +#athenz.zts.service_certificate_path=/var/lib/sia/certs/athenz.zts.cert.pem + +# If configured, specifies a file name that contains the bundle of Athenz +# CA certificates. This is useful when there are multiple Athenz instances +# running in different regions/locations and each region/location has its own +# CA certificate and during instance register/refresh operation we want to +# return the full set of CA certs +#athenz.zts.x509_ca_cert_fname=/opt/zts/conf/athenz_certificate_bundle.pem diff --git a/aws-setup/zts-setup/build/service/zts.service b/aws-setup/zts-setup/build/service/zts.service new file mode 100755 index 00000000000..e1e03c37ea9 --- /dev/null +++ b/aws-setup/zts-setup/build/service/zts.service @@ -0,0 +1,14 @@ +[Unit] +Description=Athenz ZTS Service +Wants=network-online.target ntpd.service +After=network-online.target + +[Service] +ExecStart=/opt/zts/bin/zts.sh +Restart=on-failure +RestartSec=20 +User=athenz-zts +Group=athenz + +[Install] +WantedBy=multi-user.target diff --git a/aws-setup/zts-setup/cloud-formation/athens-zts-aws-instance-deployment.yaml b/aws-setup/zts-setup/cloud-formation/athens-zts-aws-instance-deployment.yaml new file mode 100644 index 00000000000..1e0cbd89aee --- /dev/null +++ b/aws-setup/zts-setup/cloud-formation/athens-zts-aws-instance-deployment.yaml @@ -0,0 +1,179 @@ +Description: 'Athenz ZTS standard 2 Availabilty zone instance deployment template' +Parameters: + ServiceRole: + Type: String + Description: The ZTS Service IAM Role Name + Default: "athenz.zts-service" + KeyName: + Type: String + Description: The EC2 key pair for the instance + ServiceName: + Type: String + Description: The service name for ZTS server + Default: "zts" + ResourceStackName: + Type: String + Description: Name of Stack used to create AWS Resources + Environment: + Type: String + Description: The environment ZTS is running in + AllowedValues: + - prod + - stage + - dev + ImageId: + Type: AWS::EC2::Image::Id + Description: "The ImageId to use for the EC2 instance. Should be a format like ami-XXXXXXXX" + AutoScalingMinSize: + Type: String + Description: The minimum instances for auto scaling + Default: "2" + AutoScalingMaxSize: + Type: String + Description: The maximum instances for auto scaling + Default: "4" + AutoScalingDesiredCapacity: + Type: String + Description: The desired number of instances + Default: "2" + EbsOptimized: + Type: String + Description: TIf EBS is to be optimized + AllowedValues: + - "true" + - "false" + Default: "false" + Ec2InstanceType: + Type: String + Description: The instance type to use for the host + Default: t2.large + AllowedValues: + - t2.nano + - t2.micro + - t2.small + - t2.medium + - t2.large + - t2.xlarge + - t2.2xlarge + - m4.large + - m4.xlarge + - m4.2xlarge + - m4.4xlarge + - m4.10xlarge + - m4.16xlarge + - m5.large + - m5.xlarge + - m5.2xlarge + - m5.4xlarge + - m5.12xlarge + - m5.24xlarge + - m5d.large + - m5d.xlarge + - m5d.2xlarge + - m5d.4xlarge + - m5d.12xlarge + - m5d.24xlarge + EbsVolumeType: + Type: String + Description: The value for EBS Volume type in Block Device Mappings for Launch Configuration + Default: "gp2" + EbsVolumeSize: + Type: Number + Description: The value for EBS Volume size Block Device Mappings for Launch Configuration + Default: "50" +Resources: + ZTSEC2AutoScalingGroup: + Type: 'AWS::AutoScaling::AutoScalingGroup' + Properties: + LaunchConfigurationName: !Ref ZTSLaunchConfig + LoadBalancerNames: + - Fn::ImportValue: !Sub "${ResourceStackName}-LoadBalancerName" + MaxSize: !Ref AutoScalingMaxSize + MinSize: !Ref AutoScalingMinSize + Cooldown: 300 + VPCZoneIdentifier: + - Fn::ImportValue: !Sub "${ResourceStackName}-PrivateSubnet01ID" + - Fn::ImportValue: !Sub "${ResourceStackName}-PrivateSubnet02ID" + DesiredCapacity: !Ref AutoScalingDesiredCapacity + HealthCheckGracePeriod: 900 + HealthCheckType: ELB + Tags: + - Key: Name + Value: !Sub ${Environment}-asg-${ServiceName}-${AWS::Region} + PropagateAtLaunch: true + - Key: Environment + Value: !Ref Environment + PropagateAtLaunch: true + - Key: Stack + Value: !Ref AWS::StackName + PropagateAtLaunch: true + ZTSEC2IncreaseGroupSizeScalingPolicy: + Type: "AWS::AutoScaling::ScalingPolicy" + Properties: + AdjustmentType: ChangeInCapacity + AutoScalingGroupName: !Ref ZTSEC2AutoScalingGroup + Cooldown: 180 + ScalingAdjustment: 1 + CPUAlarmHigh: + Type: AWS::CloudWatch::Alarm + Properties: + EvaluationPeriods: '5' + Statistic: Average + Threshold: '50' + Unit: Percent + AlarmDescription: Alarm if CPU too high or metric disappears indicating instance + is down + Period: '60' + AlarmActions: + - Ref: ZTSEC2IncreaseGroupSizeScalingPolicy + Namespace: AWS/EC2 + Dimensions: + - Name: AutoScalingGroupName + Value: + Ref: ZTSEC2AutoScalingGroup + ComparisonOperator: GreaterThanThreshold + MetricName: CPUUtilization + ZTSEC2DecreaseGroupSizeScalingPolicy: + Type: "AWS::AutoScaling::ScalingPolicy" + Properties: + AdjustmentType: ChangeInCapacity + AutoScalingGroupName: !Ref ZTSEC2AutoScalingGroup + Cooldown: 300 + ScalingAdjustment: -1 + CPUAlarmLow: + Type: AWS::CloudWatch::Alarm + Properties: + EvaluationPeriods: '5' + Statistic: Average + Threshold: '20' + Unit: Percent + AlarmDescription: Alarm if CPU too low + is down + Period: '60' + AlarmActions: + - Ref: ZTSEC2DecreaseGroupSizeScalingPolicy + Namespace: AWS/EC2 + Dimensions: + - Name: AutoScalingGroupName + Value: + Ref: ZTSEC2AutoScalingGroup + ComparisonOperator: LessThanThreshold + MetricName: CPUUtilization + ZTSLaunchConfig: + Type: 'AWS::AutoScaling::LaunchConfiguration' + Properties: + AssociatePublicIpAddress: false + IamInstanceProfile: !Sub arn:aws:iam::${AWS::AccountId}:instance-profile/${ServiceRole} + ImageId: !Ref ImageId + KeyName: !Ref KeyName + InstanceType: !Ref Ec2InstanceType + EbsOptimized: !Ref EbsOptimized + SecurityGroups: + - Fn::ImportValue: !Sub "${ResourceStackName}-ServerSecurityGroupID" + BlockDeviceMappings: + - DeviceName: "/dev/sda1" + Ebs: + VolumeSize: !Ref EbsVolumeSize + VolumeType: !Ref EbsVolumeType + DeleteOnTermination: true + InstanceMonitoring: true \ No newline at end of file diff --git a/aws-setup/zts-setup/cloud-formation/athens-zts-aws-rds-setup.yaml b/aws-setup/zts-setup/cloud-formation/athens-zts-aws-rds-setup.yaml new file mode 100644 index 00000000000..f2839a20da0 --- /dev/null +++ b/aws-setup/zts-setup/cloud-formation/athens-zts-aws-rds-setup.yaml @@ -0,0 +1,225 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: 'Athenz ZTS standard 2 Availabilty zone RDS configuration template' +Parameters: + ServiceName: + Type: String + Description: The service name for ZTS server + Default: "zts" + GroupName: + Type: String + Description: The Athens domain for the account + Default: "Athenz" + ResourceStackName: + Type: String + Description: Name of Stack used to create AWS Resources + Environment: + Type: String + Description: The environment ZTS is running in + AllowedValues: + - prod + - stage + - dev + DatabaseName: + Type: String + Description: Database Name + Default: "ztsstore" + MinLength: "1" + MaxLength: "64" + AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*" + ConstraintDescription: "must begin with a letter and contain only alphanumeric characters." + DatabaseUsername: + NoEcho: "true" + Type: String + Description: Database Username + Default: "dbuser" + MinLength: "1" + MaxLength: "16" + AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*" + ConstraintDescription: "must begin with a letter and contain only alphanumeric characters." + DatabasePassword: + NoEcho: "true" + Type: String + Description: Database Password + Default: "dbpasswd" + MinLength: "1" + MaxLength: "41" + AllowedPattern: "[a-zA-Z0-9]+" + ConstraintDescription: "must contain only alphanumeric characters." + DatabaseInstanceClass: + Type: String + Description: "The database instance type" + Default: "db.t2.medium" + AllowedValues: + - db.t1.micro + - db.t1.micro + - db.t1.micro + - db.t1.micro + - db.m1.small + - db.m1.medium + - db.m1.large + - db.m1.xlarge + - db.m2.xlarge + - db.m2.2xlarge + - db.m2.4xlarge + - db.m3.medium + - db.m3.large + - db.m3.xlarge + - db.m3.2xlarge + - db.m4.large + - db.m4.xlarge + - db.m4.2xlarge + - db.m4.4xlarge + - db.m4.10xlarge + - db.r3.large + - db.r3.xlarge + - db.r3.2xlarge + - db.r3.4xlarge + - db.r3.8xlarge + - db.m2.xlarge + - db.m2.2xlarge + - db.m2.4xlarge + - db.cr1.8xlarge + - db.t2.micro + - db.t2.small + - db.t2.medium + - db.t2.large" + ConstraintDescription: "must select a valid database instance type." + EncryptDatabaseStorage: + Type: String + Description: The Athens domain for the account + AllowedValues: + - "true" + - "false" + Default: "true" + Route53HostedZoneName: + Type: String + Description: The hosted zone name to place a CNAME entry for. Must end with a period. Empty string means do not create one. + Route53DatabaseRecordName: + Type: String + Description: The hosted records to be added +Conditions: + CreateDNSRecordSet: !Not [!Equals [ !Ref Route53HostedZoneName, '']] + EnableDatabaseEncryption: !Equals [ !Ref EncryptDatabaseStorage , true] + +Resources: + DatabaseSubnetGroup: + Type: AWS::RDS::DBSubnetGroup + Properties: + DBSubnetGroupDescription: CloudFormation managed DB subnet group. + DBSubnetGroupName: !Sub ${Environment}-${ServiceName}-db-subnet + SubnetIds: + - Fn::ImportValue: !Sub "${ResourceStackName}-PrivateSubnet01ID" + - Fn::ImportValue: !Sub "${ResourceStackName}-PrivateSubnet02ID" + DatabaseCluster: + Type: AWS::RDS::DBCluster + Properties: + Engine: aurora + DatabaseName: !Ref "DatabaseName" + MasterUsername: !Ref "DatabaseUsername" + MasterUserPassword: !Ref "DatabasePassword" + BackupRetentionPeriod: 7 + PreferredBackupWindow: 01:00-02:00 + PreferredMaintenanceWindow: mon:03:00-mon:04:00 + DBSubnetGroupName: !Ref "DatabaseSubnetGroup" + VpcSecurityGroupIds: [!Ref "ZTSDBVPCSecurityGroup"] + StorageEncrypted: !Ref EncryptDatabaseStorage + KmsKeyId: !If [EnableDatabaseEncryption, !GetAtt DatabaseEncryptionKey.Arn, !Ref "AWS::NoValue"] + ZTSDBVPCSecurityGroup: + Type: "AWS::EC2::SecurityGroup" + Properties: + GroupName: !Sub ${GroupName}-${Environment}-rds-sg-${ServiceName}-${AWS::Region} + GroupDescription: 'ZTS public db security group' + SecurityGroupIngress: + - IpProtocol: TCP + FromPort: '3306' + ToPort: '3306' + CidrIp: '10.0.0.0/20' + VpcId: + Fn::ImportValue: !Sub "${ResourceStackName}-VPCID" + Tags: + - Key: Name + Value: !Sub ${Environment}-rds-sg-${ServiceName}-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + DatabaseEncryptionKey: + Type: 'AWS::KMS::Key' + Condition: EnableDatabaseEncryption + Properties: + Description: "KMS key for database encryption" + EnableKeyRotation: true + Enabled: true + KeyPolicy: + Version: 2012-10-17 + Id: key-default-1 + Statement: + - Sid: Enable IAM User Permissions + Effect: Allow + Principal: + AWS: !Sub arn:aws:iam::${AWS::AccountId}:root + Action: 'kms:*' + Resource: '*' + Tags: + - Key: Name + Value: !Sub ${DatabaseName}-${AWS::Region}-encryption-key + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + DatabaseEncryptionKeyAlias: + Type: AWS::KMS::Alias + Condition: EnableDatabaseEncryption + Properties: + AliasName: !Sub alias/${DatabaseName}-${AWS::Region}-encryption-key + TargetKeyId: !Ref DatabaseEncryptionKey + DatabasePrimaryInstance: + Type: AWS::RDS::DBInstance + Properties: + Engine: aurora + DBClusterIdentifier: !Ref "DatabaseCluster" + DBInstanceClass: !Ref DatabaseInstanceClass + DBSubnetGroupName: !Ref "DatabaseSubnetGroup" + PubliclyAccessible: "false" + DBInstanceIdentifier: !Ref "DatabaseName" + Tags: + - Key: Name + Value: !Ref "DatabaseName" + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + DatabaseReplicaInstance: + Type: AWS::RDS::DBInstance + Properties: + Engine: aurora + DBClusterIdentifier: !Ref "DatabaseCluster" + DBInstanceClass: !Ref DatabaseInstanceClass + DBSubnetGroupName: !Ref "DatabaseSubnetGroup" + PubliclyAccessible: "false" + DBInstanceIdentifier: !Sub ${DatabaseName}-${AWS::Region} + Tags: + - Key: Name + Value: !Sub ${DatabaseName}-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + ZTSDatabaseRecordSet: + Type: AWS::Route53::RecordSet + Condition: CreateDNSRecordSet + Properties: + Comment: CNAME record for the ZTS DB. + HostedZoneName: !Ref Route53HostedZoneName + Name: !Ref Route53DatabaseRecordName + TTL: 60 + Type: CNAME + ResourceRecords: + - !GetAtt DatabaseCluster.Endpoint.Address +Outputs: + DatabasePrimaryInstanceEndpoint: + Description: Endpoint for primary database + Value: !GetAtt DatabasePrimaryInstance.Endpoint.Address + DatabaseReplicaInstanceEndpoint: + Description: Endpoint for primary database + Value: !GetAtt DatabaseReplicaInstance.Endpoint.Address \ No newline at end of file diff --git a/aws-setup/zts-setup/cloud-formation/athens-zts-aws-resource-setup.yaml b/aws-setup/zts-setup/cloud-formation/athens-zts-aws-resource-setup.yaml new file mode 100644 index 00000000000..146c0bd818d --- /dev/null +++ b/aws-setup/zts-setup/cloud-formation/athens-zts-aws-resource-setup.yaml @@ -0,0 +1,813 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: 'Athenz ZTS standard 2 Availabilty zone configuration template' +Parameters: + ZTSServiceName: + Type: String + Description: The service name for ZTS server + Default: "zts" + ZTSVPCCidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the ZTS VPC. + Default: "10.0.0.0/18" + PrivateSubnet01CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Private Subnet Zone 1. + Default: "10.0.0.0/22" + PrivateSubnet02CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Private Subnet Zone 2. + Default: "10.0.4.0/22" + PublicSubnet01CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Public Subnet Zone 1. + Default: "10.0.8.0/22" + PublicSubnet02CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Public Subnet Zone 2. + Default: "10.0.12.0/22" + CertSignerPrivateSubnet01CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Cert Signer Private Subnet Zone 1. + Default: "10.0.16.0/22" + CertSignerPrivateSubnet02CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Cert Signer Private Subnet Zone 2. + Default: "10.0.20.0/22" + CertSignerPublicSubnet01CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Cert Signer Public Subnet Zone 1. + Default: "10.0.26.0/23" + CertSignerPublicSubnet02CidrBlock: + AllowedPattern: "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})" + ConstraintDescription: "must be an IP address block in Cidr notation." + MaxLength: "18" + MinLength: "9" + Type: String + Description: The CIDR block to use for the Cert Signer Public Subnet Zone 2. + Default: "10.0.30.0/23" + GroupName: + Type: String + Description: The Athens domain for the account + Default: "Athenz" + Environment: + Type: String + Description: The environment ZTS is running in + AllowedValues: + - prod + - stage + - dev + S3AccessLogBucketName: + Type: String + Description: S3 bucket name to store access logs + Route53HostedZoneName: + Type: String + Description: The hosted zone name to place a CNAME entry for. Must end with a period. Empty string means do not create one. + Route53RecordName: + Type: String + Description: The hosted records to be added +Conditions: + CreateDNSRecordSet: !Not [!Equals [ !Ref Route53HostedZoneName, '']] +Resources: + ZTSVPC: + Type: 'AWS::EC2::VPC' + Properties: + CidrBlock: !Ref 'ZTSVPCCidrBlock' + EnableDnsSupport: true + EnableDnsHostnames: true + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZTSServiceName} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet01: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PrivateSubnet01CidrBlock' + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZTSServiceName}-${AWS::Region}a-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet02: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 1 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PrivateSubnet02CidrBlock' + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZTSServiceName}-${AWS::Region}b-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet01: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PublicSubnet01CidrBlock' + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZTSServiceName}-${AWS::Region}a-public + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet02: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 1 + - Fn::GetAZs: "" + CidrBlock: !Ref 'PublicSubnet02CidrBlock' + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZTSServiceName}-${AWS::Region}b-public + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + CertSignerPrivateSubnet01: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: "" + CidrBlock: !Ref 'CertSignerPrivateSubnet01CidrBlock' + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-certsignd-${AWS::Region}a-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + CertSignerPrivateSubnet02: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 1 + - Fn::GetAZs: "" + CidrBlock: !Ref 'CertSignerPrivateSubnet02CidrBlock' + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-certsignd-${AWS::Region}b-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + CertSignerPublicSubnet01: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: "" + CidrBlock: !Ref 'CertSignerPublicSubnet01CidrBlock' + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-certsignd-${AWS::Region}a-public + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + CertSignerPublicSubnet02: + Type: 'AWS::EC2::Subnet' + Properties: + AvailabilityZone: + Fn::Select: + - 1 + - Fn::GetAZs: "" + CidrBlock: !Ref 'CertSignerPublicSubnet02CidrBlock' + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-certsignd-${AWS::Region}b-public + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + Nacl: + Type: "AWS::EC2::NetworkAcl" + Properties: + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZTSServiceName} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + NetworkAclEntry01: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '100' + Protocol: "6" + RuleAction: allow + CidrBlock: !Ref 'ZTSVPCCidrBlock' + PortRange: + From: '22' + To: '22' + NetworkAclEntry02: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '110' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '4443' + To: '4443' + NetworkAclEntry03: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '120' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '8443' + To: '8443' + NetworkAclEntry04: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '130' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '3306' + To: '3306' + NetworkAclEntry05: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '140' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '80' + To: '80' + NetworkAclEntry06: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '150' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '443' + To: '443' + NetworkAclEntry07: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '160' + Protocol: "17" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '123' + To: '123' + NetworkAclEntry08: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + Egress: 'true' + RuleNumber: '200' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '1024' + To: '65535' + NetworkAclEntry09: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '100' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '22' + To: '22' + NetworkAclEntry10: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '110' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '4443' + To: '4443' + NetworkAclEntry11: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '120' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '8443' + To: '8443' + NetworkAclEntry12: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '130' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '3306' + To: '3306' + NetworkAclEntry13: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '140' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '80' + To: '80' + NetworkAclEntry14: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '150' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '443' + To: '443' + NetworkAclEntry15: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '160' + Protocol: "17" + RuleAction: allow + CidrBlock: !Ref 'ZTSVPCCidrBlock' + PortRange: + From: '123' + To: '123' + NetworkAclEntry16: + Type: AWS::EC2::NetworkAclEntry + Properties: + NetworkAclId: !Ref 'Nacl' + RuleNumber: '200' + Protocol: "6" + RuleAction: allow + CidrBlock: 0.0.0.0/0 + PortRange: + From: '1024' + To: '65535' + PrivateSubnet01Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PrivateSubnet01' + NetworkAclId: !Ref 'Nacl' + PrivateSubnet02Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PrivateSubnet02' + NetworkAclId: !Ref 'Nacl' + PublicSubnet01Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PublicSubnet01' + NetworkAclId: !Ref 'Nacl' + PublicSubnet02Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'PublicSubnet02' + NetworkAclId: !Ref 'Nacl' + CertSignerPrivateSubnet01Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'CertSignerPrivateSubnet01' + NetworkAclId: !Ref 'Nacl' + CertSignerPrivateSubnet02Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'CertSignerPrivateSubnet02' + NetworkAclId: !Ref 'Nacl' + CertSignerPublicSubnet01Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'CertSignerPublicSubnet01' + NetworkAclId: !Ref 'Nacl' + CertSignerPublicSubnet02Nacl: + Type: "AWS::EC2::SubnetNetworkAclAssociation" + Properties: + SubnetId: !Ref 'CertSignerPublicSubnet02' + NetworkAclId: !Ref 'Nacl' + InternetGateway: + Type: "AWS::EC2::InternetGateway" + Properties: + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZTSServiceName} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + VPCGatewayAttachment: + Type: "AWS::EC2::VPCGatewayAttachment" + Properties: + InternetGatewayId: !Ref 'InternetGateway' + VpcId: !Ref 'ZTSVPC' + PublicSubnet01NatGateway: + Type: "AWS::EC2::NatGateway" + Properties: + AllocationId: !GetAtt PublicSubnet01EIP.AllocationId + SubnetId: !Ref 'PublicSubnet01' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZTSServiceName}-${AWS::Region}a + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet01EIP: + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + PublicSubnet02NatGateway: + Type: "AWS::EC2::NatGateway" + Properties: + AllocationId: !GetAtt PublicSubnet02EIP.AllocationId + SubnetId: !Ref 'PublicSubnet02' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZTSServiceName}-${AWS::Region}b + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PublicSubnet02EIP: + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + CertSignerPublicSubnet01NatGateway: + Type: "AWS::EC2::NatGateway" + Properties: + AllocationId: !GetAtt CertSignerPublicSubnet01EIP.AllocationId + SubnetId: !Ref 'CertSignerPublicSubnet01' + Tags: + - Key: Name + Value: !Sub ${Environment}-certsignd-${AWS::Region}a + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + CertSignerPublicSubnet01EIP: + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + CertSignerPublicSubnet02NatGateway: + Type: "AWS::EC2::NatGateway" + Properties: + AllocationId: !GetAtt CertSignerPublicSubnet02EIP.AllocationId + SubnetId: !Ref 'CertSignerPublicSubnet02' + Tags: + - Key: Name + Value: !Sub ${Environment}-certsignd-${AWS::Region}b + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + CertSignerPublicSubnet02EIP: + DependsOn: VPCGatewayAttachment + Type: AWS::EC2::EIP + Properties: + Domain: vpc + PublicSubnetRouteTable: + Type: "AWS::EC2::RouteTable" + Properties: + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZTSServiceName}-${AWS::Region}-public + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + GatewayRoute: + Type: "AWS::EC2::Route" + Properties: + DestinationCidrBlock: '0.0.0.0/0' + GatewayId: !Ref 'InternetGateway' + RouteTableId: !Ref 'PublicSubnetRouteTable' + DependsOn: VPCGatewayAttachment + PrivateSubnet01RouteTable: + Type: "AWS::EC2::RouteTable" + Properties: + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZTSServiceName}-${AWS::Region}a-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet01Route: + Type: "AWS::EC2::Route" + Properties: + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'PublicSubnet01NatGateway' + RouteTableId: !Ref 'PrivateSubnet01RouteTable' + PrivateSubnet02RouteTable: + Type: "AWS::EC2::RouteTable" + Properties: + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-${ZTSServiceName}-${AWS::Region}b-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + PrivateSubnet02Route: + Type: "AWS::EC2::Route" + Properties: + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'PublicSubnet02NatGateway' + RouteTableId: !Ref 'PrivateSubnet02RouteTable' + DependsOn: VPCGatewayAttachment + CertSignerPrivateSubnet01RouteTable: + Type: "AWS::EC2::RouteTable" + Properties: + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-certsignd-${AWS::Region}a-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + CertSignerPrivateSubnet01Route: + Type: "AWS::EC2::Route" + Properties: + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'CertSignerPublicSubnet01NatGateway' + RouteTableId: !Ref 'CertSignerPrivateSubnet01RouteTable' + CertSignerPrivateSubnet02RouteTable: + Type: "AWS::EC2::RouteTable" + Properties: + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-certsignd-${AWS::Region}b-private + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + CertSignerPrivateSubnet02Route: + Type: "AWS::EC2::Route" + Properties: + DestinationCidrBlock: '0.0.0.0/0' + NatGatewayId: !Ref 'CertSignerPublicSubnet02NatGateway' + RouteTableId: !Ref 'CertSignerPrivateSubnet02RouteTable' + DependsOn: VPCGatewayAttachment + PublicSubnet01RouteTableAssociaton: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PublicSubnetRouteTable' + SubnetId: !Ref 'PublicSubnet01' + PublicSubnet02RouteTableAssociaton: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PublicSubnetRouteTable' + SubnetId: !Ref 'PublicSubnet02' + CertSignerPublicSubnet01RouteTableAssociaton: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PublicSubnetRouteTable' + SubnetId: !Ref 'CertSignerPublicSubnet01' + CertSignerPublicSubnet02RouteTableAssociaton: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PublicSubnetRouteTable' + SubnetId: !Ref 'CertSignerPublicSubnet02' + PrivateSubnet01RouteTableAssociation: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PrivateSubnet01RouteTable' + SubnetId: !Ref 'PrivateSubnet01' + PrivateSubnet02RouteTableAssociation: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'PrivateSubnet02RouteTable' + SubnetId: !Ref 'PrivateSubnet02' + CertSignerPrivateSubnet01RouteTableAssociation: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'CertSignerPrivateSubnet01RouteTable' + SubnetId: !Ref 'CertSignerPrivateSubnet01' + CertSignerPrivateSubnet02RouteTableAssociation: + Type: "AWS::EC2::SubnetRouteTableAssociation" + Properties: + RouteTableId: !Ref 'CertSignerPrivateSubnet02RouteTable' + SubnetId: !Ref 'CertSignerPrivateSubnet02' + ZTSELBSecurityGroup: + Type: "AWS::EC2::SecurityGroup" + Properties: + GroupName: !Sub ${GroupName}-${Environment}-elb-sg-${ZTSServiceName}-${AWS::Region} + GroupDescription: 'ZTS public elb security group' + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: '4443' + ToPort: '4443' + CidrIp: '0.0.0.0/0' + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-elb-${ZTSServiceName}-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + ZTSServerSecurityGroup: + Type: "AWS::EC2::SecurityGroup" + Properties: + GroupName: !Sub ${GroupName}-${Environment}-server-sg-${ZTSServiceName}-${AWS::Region} + GroupDescription: 'ZTS public server security group' + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: '4443' + ToPort: '4443' + CidrIp: '0.0.0.0/0' + - IpProtocol: tcp + FromPort: '8443' + ToPort: '8443' + CidrIp: !Ref 'ZTSVPCCidrBlock' + VpcId: !Ref 'ZTSVPC' + Tags: + - Key: Name + Value: !Sub ${Environment}-server-${ZTSServiceName}-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + ZTSLoadBalancer: + Type: "AWS::ElasticLoadBalancing::LoadBalancer" + Properties: + HealthCheck: + HealthyThreshold: 2 + Interval: 10 + Target: !Sub HTTPS:8443/${ZTSServiceName}/v1/status + Timeout: 5 + UnhealthyThreshold: 2 + Listeners: + - InstancePort: 4443 + InstanceProtocol: TCP + LoadBalancerPort: 4443 + Protocol: TCP + Policies: + - PolicyName: "EnableProxyProtocol" + PolicyType: "ProxyProtocolPolicyType" + Attributes: + - Name: ProxyProtocol + Value: 'true' + InstancePorts: + - '4443' + LoadBalancerName: !Sub ${Environment}-elb-${ZTSServiceName}-${AWS::Region} + Scheme: 'internet-facing' + ConnectionDrainingPolicy: + Enabled: 'true' + Timeout: '60' + CrossZone: true + SecurityGroups: + - !Ref ZTSELBSecurityGroup + Subnets: + - !Ref 'PublicSubnet01' + - !Ref 'PublicSubnet02' + AccessLoggingPolicy: + S3BucketName: !Ref S3AccessLogBucketName + S3BucketPrefix: !Sub elb-${ZTSServiceName} + Enabled: 'true' + EmitInterval: '60' + Tags: + - Key: Name + Value: !Sub ${Environment}-elb-ZTS-${AWS::Region} + - Key: Environment + Value: !Ref Environment + - Key: Stack + Value: !Ref AWS::StackName + ZTSRecordSet: + Type: AWS::Route53::RecordSet + Condition: CreateDNSRecordSet + Properties: + Comment: CNAME record for the ZTS Server. + HostedZoneName: !Ref Route53HostedZoneName + Name: !Ref Route53RecordName + TTL: 60 + Type: CNAME + ResourceRecords: + - !GetAtt ZTSLoadBalancer.DNSName +Outputs: + ZTSVPCID: + Description: The ID of the ZTS VPC + Value: !Ref ZTSVPC + Export: + Name: !Sub "${AWS::StackName}-VPCID" + PrivateSubnet01ID: + Description: The ID of Private Subnet Availability Zone 1 in ZTS VPC + Value: !Ref PrivateSubnet01 + Export: + Name: !Sub "${AWS::StackName}-PrivateSubnet01ID" + PrivateSubnet02ID: + Description: The ID of Private Subnet Availability Zone 2 in ZTS VPC + Value: !Ref PrivateSubnet02 + Export: + Name: !Sub "${AWS::StackName}-PrivateSubnet02ID" + LoadBalancerName : + Description: The name of ZTS Load Balancer + Value: !Ref ZTSLoadBalancer + Export: + Name: !Sub "${AWS::StackName}-LoadBalancerName" + ServerSecurityGroupID: + Description: The ID of ZTS Server security group + Value: !Ref ZTSServerSecurityGroup + Export: + Name: !Sub "${AWS::StackName}-ServerSecurityGroupID" + + \ No newline at end of file diff --git a/aws-setup/zts-setup/cloud-formation/athens-zts-aws-roles-setup.yaml b/aws-setup/zts-setup/cloud-formation/athens-zts-aws-roles-setup.yaml new file mode 100644 index 00000000000..6a9ffff64cb --- /dev/null +++ b/aws-setup/zts-setup/cloud-formation/athens-zts-aws-roles-setup.yaml @@ -0,0 +1,52 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: Roles needed for athens zts setup +Parameters: + AthensServiceRole: + Type: String + Description: The Athens role name for the service + Default: athenz.zts-service +Resources: + AthensServiceEC2Role: + Type: "AWS::IAM::Role" + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - + Effect: "Allow" + Principal: + Service: + - "ec2.amazonaws.com" + Action: + - "sts:AssumeRole" + Policies: + - + PolicyName: !Sub ${AthensServiceRole}.policy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + - logs:DescribeLogStreams + - logs:DescribeLogGroups + Resource: "arn:aws:logs:*:*:*" + - Effect: "Allow" + Action: + - rds-db:connect + Resource: + - !Sub arn:aws:rds-db:us-west-2:${AWS::AccountId}:dbuser:*/zts + - !Sub arn:aws:rds-db:us-east-1:${AWS::AccountId}:dbuser:*/zts + - Effect: "Allow" + Action: "ec2:DescribeTags" + Resource: "*" + Path: / + RoleName: !Ref AthensServiceRole + AthensEc2InstanceProfile: + Type: "AWS::IAM::InstanceProfile" + Properties: + Roles: + - !Ref AthensServiceEC2Role + InstanceProfileName: !Ref AthensServiceRole \ No newline at end of file diff --git a/aws-setup/zts-setup/packer/aws/packer.json b/aws-setup/zts-setup/packer/aws/packer.json new file mode 100755 index 00000000000..cc5b4de4c33 --- /dev/null +++ b/aws-setup/zts-setup/packer/aws/packer.json @@ -0,0 +1,106 @@ +{ + "variables": { + "subnet_id":"subnet-xxxxxxxxx", + "vpc_id": "vpc-xxxxxxxxxxxxxx", + "aws_region": "{{env `AWS_REGION`}}", + "aws_ami_name": "zts-aws-cd-image", + "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}", + "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}", + "aws_session_token": "{{env `AWS_SESSION_TOKEN`}}", + "ssh_keypair_name":"keypair-name", + "ssh_private_key_file":"path to ssh key file", + "source_ami": "ami-02c71d7a" + }, + "builders": [ + { + "access_key": "{{user `aws_access_key`}}", + "secret_key": "{{user `aws_secret_key`}}", + "token": "{{user `aws_session_token`}}", + "name": "amazon-ebs", + "ssh_username": "centos", + "ssh_keypair_name":"{{user `ssh_keypair_name`}}", + "ssh_private_key_file":"{{user `ssh_private_key_file`}}", + "type": "amazon-ebs", + "region": "{{user `aws_region`}}", + "source_ami": "{{user `source_ami`}}", + "ami_block_device_mappings": [ + { + "device_name": "/dev/sda1", + "volume_type": "gp2", + "volume_size": 50, + "encrypted": true, + "delete_on_termination": true + } + ], + "encrypt_boot": true, + "instance_type": "t2.micro", + "ami_name": "{{user `aws_ami_name`}}", + "ami_description": "ZMS Image for cloud formation", + "associate_public_ip_address": "true", + "subnet_id": "{{ user `subnet_id` }}", + "vpc_id": "{{ user `vpc_id` }}" + }], + + "provisioners": [ + { + "type": "shell", + "execute_command": "echo {{user `ssh_username`}} | {{ .Vars }} sudo -E -S sh '{{ .Path }}'", + "inline": [ + "mkdir -p /opt", + "chmod a+w /opt" + ] + }, + { + "type": "shell", + "execute_command": "echo {{user `ssh_username`}} | {{ .Vars }} sudo -E -S sh '{{ .Path }}'", + "inline": [ + "mkdir -p /opt/zts/tars", + "mkdir -p /opt/zts/jars", + "mkdir -p /opt/zts/logs", + "mkdir -p /opt/zts/domains", + "mkdir -p /opt/zts/webapps", + "mkdir -p /opt/zts/etc", + "mkdir -p /opt/zts/bin", + "mkdir -p /opt/zts/temp", + "mkdir -p /opt/zts/service", + "mkdir -p /opt/zts/conf", + "mkdir /var/log/zts_server", + "chmod 777 /opt/zts -R" + ] + }, + { + "type": "file", + "source": "build/bin/", + "destination": "/opt/zts/bin/" + }, + { + "type": "file", + "source": "build/conf/", + "destination": "/opt/zts/conf/" + }, + { + "type": "file", + "source": "build/service/", + "destination": "/opt/zts/service" + }, + { + "type": "file", + "source": "tars/", + "destination": "/opt/zts/tars/" + }, + { + "type": "shell", + "execute_command": "echo {{user `ssh_username`}} | {{ .Vars }} sudo -E -S sh '{{ .Path }}'", + "inline": [ + "ls -ltr /opt/" + ] + }, + { + "type": "shell", + "scripts": [ + "packer/scripts/setup.sh" + ], + "execute_command": "chmod +x {{ .Path }}; {{ .Vars }} sudo -E '{{ .Path }}'" + } + ] +} diff --git a/aws-setup/zts-setup/packer/scripts/setup.sh b/aws-setup/zts-setup/packer/scripts/setup.sh new file mode 100755 index 00000000000..5f1747f93ec --- /dev/null +++ b/aws-setup/zts-setup/packer/scripts/setup.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +set -xe + +# install epel + +sudo yum -y install epel-release +sudo yum repolist + +# install aws_cli + +echo "install aws" +sudo yum -y install python-pip +sudo pip install awscli +aws --version + +# install openjdk + +sudo yum -y install java-1.8.0-openjdk + +# setup our athenz group and user + +sudo groupadd athenz +sudo useradd -g athenz athenz-zts + + +# Copying jars, war and webdefault.xml files +sudo tar -xzf /opt/zts/tars/athenz-zts-bin.tar.gz -C /opt/zts/tars/ +sudo ls -ltr /opt/zts/tars/ +sudo cp -r /opt/zts/tars/athenz-zts/lib/jars/ /opt/zts/ +sudo cp /opt/zts/tars/athenz-zts/etc/webdefault.xml /opt/zts/etc/ +sudo cp /opt/zts/tars/athenz-zts/webapps/zts.war /opt/zts/webapps/ +sudo cp -r /opt/zts/tars/athenz-zts/bin/linux/ /opt/zts/bin/ + +# setup our zts service + +sudo mkdir /etc/zts +sudo cp /opt/zts/service/zts.service /etc/zts/zts.service +sudo systemctl enable /etc/zts/zts.service +sudo cp /opt/zts/conf/zts-user /etc/sudoers.d/ + +#set up aws logs + +curl https://s3.amazonaws.com//aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -o /opt/zts/logs/awslogs-agent-setup.py + +# make sure all files are owned by our user/group + +sudo chown -R athenz-zts:athenz /opt/zts diff --git a/docs/aws_athenz_setup.md b/docs/aws_athenz_setup.md new file mode 100644 index 00000000000..0b0c67d1ee2 --- /dev/null +++ b/docs/aws_athenz_setup.md @@ -0,0 +1,30 @@ +# Athenz Setup on AWS +------------------ +- [Build the project](##-build-the-projet) +- [ZMS Setup](##-zms-setup) +- [ZTS Setup](##-zms-setup) +- [ZMS Setup](##-zms-setup) + +## Build the Project +----------------- +`mvn clean install` + +Make sure to have the following tar files: + +``` +aws-setup/zms-setup/tars/athenz-zms-bin.tar.gz +aws-setup/zts-setup/tars/athenz-zts-bin.tar.gz +aws-setup/ui-setup/tars/athenz-ui-bin.tar.gz +``` + +## ZMS Setup + +Refer [AWS ZMS Setup](aws_zms_setup.md) for details + +## ZTS Setup + +Refer [AWS ZTS Setup](aws_zts_setup.md) for details + +## UI Setup + +Refer [AWS UI Setup](aws_ui_setup.md) for details diff --git a/docs/aws_ui_setup.md b/docs/aws_ui_setup.md new file mode 100644 index 00000000000..276bf6c7607 --- /dev/null +++ b/docs/aws_ui_setup.md @@ -0,0 +1,185 @@ +# Setup UI on AWS +------------------- +- [AWS Resource Setup](###-aws-resource-setup) + - [IAM role setup](####-iam-role-setup) + - [VPC setup](####-vpc-setup) + - [S3 bucket for UI data](####-create-s3-bucket-to-store-ui-data) + - [Generate and upload service private key](#####-generate-and-upload-service-private-key) + - [Upload server X.509 cert and key](#####-upload-server-x.509-cert-and-key) + - [Upload ZMS CA Certs](#####-upload-zms-ca-certs) + - [Upload ZMS Public key](#####-upload-zms-public-key) + - [Update ZMS DATA BUCKET](####-update-zms-data-bucket) + - [Register UI Service](####-register-ui-service) + - [Packer](####-packer) + - [Packer VPC setup](#####-packer-vpc-setup) + - [Build UI Image](#####-build-ui-image) + - [Deploy UI](####deploy-ui) + +## AWS Resource Setup +------------- + +### IAM role setup +-- +Create EC2 profile role for UI using cloudformation [template](https://github.com/yahoo/athenz/blob/master/aws-setup/ui-setup/cloud-formation/athens-ui-aws-roles-setup.yaml). This template creates a role named `athenz.ui-service` + +### VPC Setup +-- +Setup VPC using the cloudformation [template](https://github.com/yahoo/athenz/blob/master/aws-setup/ui-setup/cloud-formation/athens-ui-aws-resource-setup.yaml) and giving the following mandatory parameters +- `Route53HostedZoneName` +- `Route53RecordName` +- `S3AccessLogBucketName`(Created during Zms Setup) +- `Environment` + +The other parameters are set by default. Change them as per your requirement + +*NOTE - Modifying the other defaults might require subsequent changes.* + +Following resources will be created after executing the template +1. 2 availability zones +1. Public & Private subnets for ui in each availability zone +1. 2 NAT gateways and elastic IPs +1. NACL's for the subnets +1. Internet gateways for all public subnets +1. Route tables for all subnets +1. Elastic load balancer +1. Route 53 DNS entry +1. UI server & ELB security groups + + +### Create S3 bucket to store UI data +-------------------------------------- + +Create S3 bucket for storing ui certificates & keys with appropriate policy as follows +``` +{ +"Version": "2012-10-17", +"Statement": [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam:::role/athenz.ui-service" + }, + "Action": "s3:GetObject", + "Resource": "arn:aws:s3::: /*" + } + ] +} +``` +Also enable Default Encryption for your bucket. + +*NOTE - athenz.ui-service is the EC2 role created using IAM template above* + +#### Generate and upload service private key +-- +Generate a unique private key that UI Server will use to sign user's authorized service tokens. +The UI has already been authorized to be allowed to carry out the users' requested operations. +``` +openssl genrsa -out service_private_key 2048 +openssl rsa -in service_private_key -pubout > ui_service_x509_key_public +``` +Upload the service private key with name `service_private_key` onto the s3 bucket + +#### Upload server X.509 cert and key +-- +NOTE - For Athenz UI production server it is strongly recommended to purchase a +certificate for HTTPS access from a well known certificate authority. +Follow the instructions provided by the Certificate Authority to generate your private key +and then the Certificate Request (CSR). + +However if you want to use the self signed certificate, you can generate a self signed certificate +as below + + ``` + openssl req -newkey rsa:2048 -nodes -keyout service_x509_key -x509 -days 365 -out service_x509_cer + ``` +- Verify your certs + ``` + openssl x509 -in service_x509_cert -text -noout + ``` +- Once you have received your X509 certificate and key, + - Upload the certificate on s3 bucket with name `service_x509_cert` + - Upload the private key with name `service_x509_key` + +#### Upload ZMS CA Certs + +- Upload ZMS CA Cert with key `zms_service_x509_ca_certs`. They will be needed so that UI can communicate securely with ZMS + +#### Upload ZMS Public keys + +- Upload ZMS public key with name `zms_service_x509_key_public.pem ` + +It is required to generate athenz.conf file at `/opt/athenz-ui/conf/athenz.conf` to include the ZMS Server URL and the registered public keys that the athenz +client libraries and utilities will use to establish connection and validate any data signed by the ZMS Server: + +### Update ZMS DATA BUCKET + +- Upload UI service public key to ZMS Data Bucket with key `ui_service_x509_key_public.pem` + +### Register UI Service +In order for UI to access ZMS domain data, it must identify itself +as a registered service in ZMS. Use `zms-cli` utility to +register a new service in `athenz` domain. If ZMS Servers are +running with a X509 certificate from a well know certificate +authority (not a self-signed one) we don't need to reference the CA +cert like we are doing below for self signed certs. + +Login into your zms-server instance as domain admin you created during zms setup and run the below commands: + +``` +- Download ZMS CA Certs(If using self signed certs) + aws s3 cp s3:///zms_service_x509_ca_certs /tmp/zms_service_x509_ca_certs +- Download UI public key + aws s3 cp s3:// /ui_service_x509_key_public.pem/tmp/ui_service_x509_key_public.pem +- Add a new domain named `athenz` + /opt/zms/bin/zms-cli -c /tmp/service_x509_ca_certs -z -add-domain athenz +- Register Service using zms-cli + /opt/zms/bin/zms-cli -c /tmp/service_x509_ca_certs -z -d athenz add-service ui 0 /tmp/ui_service_x509_key_public.pem +``` +*NOTE - Append /zms/v1 to your url in the command above* + +For e.g. If your zms server is running at https://athenz.zms.com:4443 then pass `https://athenz.zms.com:4443/zms/v1`. + +### Packer +-- +#### Packer VPC Setup + +Packer VPC was set during zms setup, update `packer.json` accordingly. +``` +{ + "subnet_id":"", + "vpc_id": "", + "aws_region": "", + "aws_ami_name": "ui-aws-cd-image", + "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}", + "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}", + "aws_session_token": "{{env `AWS_SESSION_TOKEN`}}", + "ssh_keypair_name":"", + "ssh_private_key_file":"", + "source_ami": "ami-02c71d7a" +} +``` + +#### Build UI image +-- +Build the image with packer using the following command + +``` +cd /aws-setup/ui-setup +packer build packer/aws/packer.json +``` + +### Deploy UI +-- +Run cloud formation [template](https://github.com/yahoo/athenz/blob/master/aws-setup/ui-setup/cloud-formation/athenz-ui-aws-instance-deployment.yaml) to bring up the ui-instances in 2 availability zones. +- The imageID parameter should be set to the image created in above step. + +The UI Server is now up and running. + +*NOTE - If using self-signed X509 certificates for Athenz ZMS and UI servers, the administrator +must add exceptions when accessing Athenz UI or install the self-signed certificates for those +two servers into his/her own web browser. The administrator must first access the ZMS Server +endpoint in the browser to accept the exception since the Athenz UI contacts ZMS Server to get +an authorized token for the user when logging in. +Alternatively, the administrator may decide to install the self-signed certificates for the ZMS and UI servers in their browser.* + diff --git a/docs/aws_zms_setup.md b/docs/aws_zms_setup.md new file mode 100644 index 00000000000..1009f4dd425 --- /dev/null +++ b/docs/aws_zms_setup.md @@ -0,0 +1,331 @@ +# Setup ZMS on AWS +------------------- +- [AWS Resource Setup](###-aws-resource-setup) + - [IAM role setup](####-iam-role-setup) + - [S3 bucket for ELB logs](####-s3-bucket-for-elb-logs) + - [VPC setup](####-vpc-setup) + - [RDS Setup](####-rds-setup) + - [Create Aurora Mysql cluster](#####-create-an-aurora-mysql-cluster) + - [Schema setup](#####-set-up-the-schema) + - [S3 bucket to store zms data](####-create-s3-bucket-to-store-zms-data) + - [Generate and upload service private key](#####-generate-and-upload-service-private-key-and-id) + - [Upload server X.509 cert and key](#####-upload-server-x.509-cert-and-key) + - [Upload RDS CA Certs](#####-upload-rds-ca-certs) + - [Upload truststore password](#####-upload-truststore-password) + - [Upload ZMS DB User Password](#####-upload-zms-db-user-password) + - [Create S3 Bucket for Audit logs](####-create-s3-bucket-for-audit-logs) + - [Edit Variables & Properties](####-edit-variables-&-properties) + - [aws_init.sh](#####-edit-aws_init.sh) + - [zms.properties](#####-edit-the-zms.properties-file) + - [Database Access](######-database-access) + - [User Authentication](######-user-authentication) + - [Domain Admins](######-domain-admins) + - [athenz.properties](#####-edit-athenz.properties-file) + - [Truststore and Keystore Settings](#####-truststore-and-keystore-settings) + - [Packer](####-packer) + - [Packer VPC setup](#####-packer-vpc-setup) + - [Build ZMS Image](#####-build-zms-image) + - [Deploy ZMS](####deploy-zms) + +## AWS Resource Setup +------------- + +### IAM role setup +-- +Create EC2 profile role for zms using cloudformation [template](https://github.com/yahoo/athenz/blob/master/aws-setup/zms-setup/cloud-formation/athens-zms-aws-roles-setup.yaml). +This template creates a role named `athenz.zms-service` + + +### S3 bucket for ELB Access logs +-- +Create S3 bucket needed to log ELB access logs with the following bucket policy + +``` +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam:::root" + }, + "Action": "s3:PutObject", + "Resource": "arn:aws:s3:::/*/AWSLogs//*" + } + ] +} +``` +Refer [AWS ELB Documentation](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-logging-bucket-permissions) for more details on bucket policy. + +### VPC Setup +-- +Setup VPC using the cloudformation [template](https://github.com/yahoo/athenz/blob/master/aws-setup/zms-setup/cloud-formation/athens-zms-aws-resource-setup.yaml) by giving the following mandatory parameters +- `Route53HostedZoneName` +- `Route53RecordName` +- `S3AccessLogBucketName` (Created in the previous step) +- `Environment` + +The other parameters are set by default. Change them as per your requirement + +*NOTE - Modifying the other defaults might require subsequent changes.* + +Following resources will be created after executing the template +1. 2 availability zones +1. Public & Private subnet for each availability zone +1. 2 NAT gateways and elastic IPs +1. NACL's for the subnets +1. Internet gateways for all public subnets +1. Route tables for all subnets +1. Elastic load balancer +1. Route 53 DNS entry +1. ZMS Server and ELB security groups + +### RDS Setup +-- +#### Create an Aurora MySQL cluster +-- +Setup the cluster using cloudformation [template](https://github.com/yahoo/athenz/blob/master/aws-setup/zms-setup/cloud-formation/athens-zms-aws-rds-setup.yaml) by giving the below mandatory parameters + +- `Route53HostedZoneName` +- `Route53RecordName` +- `DatabaseUsername` +- `DatabasePassword` +- `Environment` + +The other parameters are set by default. Change them as per your requirement + +#### Set up the schema +-- +1. Create an instance in private subnet and login into it. +After logging in, use the following commands to connect to the cluster + ``` + mysql -h -P 3306 -u -p + ``` +1. Copy the [zms_server.sql](https://github.com/yahoo/athenz/blob/master/servers/zms/schema/zms_server.sql) file from the Athenz Git repository onto this host and create the database using the following command + ``` + mysql -h -P 3306 -u -p < zms_server.sql + ``` +1. Create a user with full privileges on zms database created above. For eg. If your ZMS Server will be running on zms1.athenz.com and user to be created is `athenz-zms` having password `athenz-zms` + ``` + CREATE USER 'athenz-zms'@'zms1.athenz.com' IDENTIFIED BY 'athenz-zms'; + GRANT ALL PRIVILEGES ON zms_server TO 'athenz-zms'@'zms1.athenz.com'; + FLUSH PRIVILEGES; + ``` + +### Create S3 bucket to store zms data +-------------------------------------- + +Create S3 bucket for storing zms certificates & keys with appropriate policy as follows +``` +{ +"Version": "2012-10-17", +"Statement": [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam:::role/athenz.zms-service" + }, + "Action": "s3:GetObject", + "Resource": "arn:aws:s3::: /*" + } + ] +} +``` +Also enable `Default Encryption` for your bucket. + +*NOTE - athenz.zms-service is the EC2 role created using IAM template above* + +#### Generate and upload service private key and id +-- +Generate a unique private key that ZMS Server will use to sign any NTokens it issues +``` +openssl genrsa -out service_private_key 2048 +openssl rsa -in service_private_key -pubout > zms_service_x509_key_public +``` +Upload the service private key with name `service_private_key` onto the s3 bucket + +Upload the service private key id with name `service_private_key_id` onto the s3 bucket. This file just contains +the id of private key. It is not mandatory as the id defaults to `0` if not specified + +#### Upload server X.509 cert and key +-- +*NOTE - While it is still possible to generate and use a self-signed X509 certificate for ZMS Servers, it is recommended to +purchase one for your production server from a well known certificate authority. Having such a certificate installed on your +ZMS Servers will no longer require to distribute the server's CA certificate to other hosts (e.g. ZTS Servers, Hosts running ZPU).* +- Follow the instructions provided by the Certificate Authority that you're going to purchase your certificate from, to generate your private key and Certificate Request (CSR). + +- If you are using self signed certs then run the following commands: + ``` + openssl genrsa -des3 -out zms_ca_key 4096 (Create ZMS CA Key) + openssl req -x509 -new -nodes -key zms_ca_key -sha256 -days 1024 -out service_x509_ca_certs (Generate CA Cert) + openssl genrsa -out service_x509_key 2048 (Generate your private key) + openssl req -new -key service_x509_key -out service_x509_csr (Generate your CSR) + openssl x509 -req -in service_x509_csr -CA service_x509_ca_certs -CAkey zms_ca_key -CAcreateserial -out service_x509_cert -days 500 -sha256 (Generate your Certificate) + ``` +- Verify your certs + ``` + openssl x509 -in service_x509_ca_certs -text -noout + openssl x509 -in service_x509_cert -text -noout + ``` +- Once you have received your X509 certificate and key, + - Upload the certificate to s3 bucket with name `service_x509_cert` + - Upload the private key with name `service_x509_key` + - Upload the Root CA cert with name `service_x509_ca_certs` + +#### Upload RDS CA Certs +--- + +RDS Certs are needed if you have set `athenz.zms.jdbc_use_ssl=` property in `zms.properties` to `true`. By default it is set to `false` + +- Upload the RDS CA Certs with key `service_rds_ca_certs` +For details on AWS RDS Certs, Please refer [RDS CERTS AWS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html) + +#### Upload truststore password +-- +- Upload password you want to use for truststore with name `service_x509_store_pwd` + +#### Upload ZMS DB User Password +-- +- Create a file containing only the password for ZMS Database user(`athenz-zms`) created above during RDS schema setup +- Upload the file to bucket with name `db_user_data` + + +### Create S3 bucket for audit logs +-- +Create another bucket for audit logs having the following bucket policy +``` +{ +"Version": "2012-10-17", +"Statement": [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "AWS": [ + "arn:aws:iam::488664618023:role/athenz.zms-service" + ] + }, + "Action": [ + "s3:AbortMultipartUpload", + "s3:GetBucketLocation", + "s3:GetObject", + "s3:ListBucket", + "s3:ListBucketMultipartUploads", + "s3:PutObject" + ], + "Resource": [ + "arn:aws:s3:::", + "arn:aws:s3:::/*" + ] + } +] +} +``` +### Edit Variables & Properties +-- +#### Edit aws_init.sh +-- +Update the bucket names, domain admin and RDS Endpoint in `athenz/aws-setup/zms-setup/build/bin/aws_init.sh` by editing the below lines +``` +export ZMS_DATA_BUCKET_NAME="" +export ZMS_AUDIT_LOG_BUCKET_NAME="" +export DOMAIN_ADMINS="" +export RDS_MASTER="" +``` +When running the server very first time, ZMS Server automatically creates the required domains and sets the running user as the system administrator. +The system administrators are the only ones authorized to create top level domains in Athenz. +Before running the server very first time, you can configure the set of system administrators who are authorized to create top level +domains in Athenz. Set DOMAIN_ADMIN to unix user id that you want to add as Athenz system administrator. +The password for this user is uploaded to ZMS Data S3 Bucket created above with name `admin_pass` + +- Create a file containing password for ZMS Domain Admin +- Upload the file to bucket with name `admin_pass` + +The other variables are for trust store & key store setup. We recommend to use the defaults but if you change then update the corresponding values in `athenz.properties` file discussed later. + +#### Edit the zms.properties file +-- +The following properties need to be edited in `zms.properties` file located at `athenz/aws-setup/zms-setup/build/conf/zms.properties` + +##### Database Access +-- +Modify the following settings if RDS username & RDS password filename (stored on S3) are different from defaults suggested above. +``` +athenz.zms.object_store_factory_class=com.yahoo.athenz.zms.store.impl.JDBCObjectStoreFactory +athenz.zms.jdbc_user=athenz-zms +athenz.zms.jdbc_password=db_user_data +``` +##### User Authentication +-- +For a user to authenticate himself/herself in ZMS, the server must have the appropriate authentication authority implementation configured. By default, ZMS enables the following two authorities: +- Unix User Authority - using pam login profile to authenticate users +- Principal Authority - validating Principal Tokens that are issued when users authenticate using their unix login password. +- This is set using the following properties + `athenz.zms.authority_classes=com.yahoo.athenz.auth.impl.PrincipalAuthority,com.yahoo.athenz.auth.impl.UserAuthority` + +The server also provides other authorities - e.g. Kerberos, TLS Certificate that are not enabled by default. + +To add your own authentication authority modify the +`athenz.zms.authority_classes=com.yahoo.athenz.auth.impl.PrincipalAuthority,com.yahoo.athenz.auth.impl.UserAuthority` +line in `zms.properties` file and include comma separated list of authority implementation classes to support. + +##### Domain Admins +-- +Modify the below setting and set it to unix user you passed as domain admin in `aws_init_file` in above steps. + +`athenz.zms.domain_admin=user.zms-admin` + +#### Edit the athenz.properties file +-- +The following properties need to be edited in `athenz.properties` file located at `athenz/aws-setup/zms-setup/build/conf/athenz.properties` + + +##### Truststore and Keystore Settings +-- +- If you modified the truststore and keystore paths and password in the `aws_init.sh` file then change the below settings in `athenz.properties` file accordingly + - `athenz.ssl_key_store=/opt/zms/conf/zms_keystore.pkcs12` `//path to the keystore file that contains the server's certificate` + - `athenz.ssl_key_store_type=PKCS12` `//specifies the type for the keystore specified in the` + - `athenz.ssl_key_store_password=service_x509_store_pwd` `//S3 bucket key name for Password for the keystore specified in the athenz.ssl_key_store property` + - `athenz.ssl_trust_store=/opt/zms/conf/zms_truststore.jks` `//path to the trust store file that contains CA certificates trusted by this Jetty instance` + - `athenz.ssl_trust_store_type=JKS` `//specifies the type for the truststore specified` + - `athenz.ssl_trust_store_password=service_x509_store_pwd` `//password for the truststore` + +### Packer +-- +#### Packer VPC Setup + +Setup packer vpc by using the cloudformation [template](https://github.com/yahoo/athenz/blob/master/aws-setup/cloud-formation/packer_vpc.yaml) +and update `packer.json` file accordingly. +``` +{ + "subnet_id":"", + "vpc_id": "", + "aws_region": "", + "aws_ami_name": "zms-aws-cd-image", + "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}", + "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}", + "aws_session_token": "{{env `AWS_SESSION_TOKEN`}}", + "ssh_keypair_name":"", + "ssh_private_key_file":"", + "source_ami": "ami-02c71d7a" +} +``` + +#### Build ZMS image +-- +Build the image with packer using the following command + +``` +cd /aws-setup/zms-setup +packer build packer/aws/packer.json +``` + +### Deploy ZMS +-- +Run cloud formation [template](https://github.com/yahoo/athenz/blob/master/aws-setup/zms-setup/cloud-formation/athenz-zms-aws-instance-deployment.yaml) to bring up the zms-instances in 2 availability zones. +- The imageID parameter should be set to the image created in previous step. + +The ZMS Server is now up and running. + diff --git a/docs/aws_zts_setup.md b/docs/aws_zts_setup.md new file mode 100644 index 00000000000..399d1fdb99d --- /dev/null +++ b/docs/aws_zts_setup.md @@ -0,0 +1,350 @@ +# Setup ZTS on AWS +------------------- +- [AWS Resource Setup](###-aws-resource-setup) + - [IAM role setup](####-iam-role-setup) + - [VPC setup](####-vpc-setup) + - [RDS Setup](####-rds-setup) + - [Create Aurora Mysql cluster](#####-create-an-aurora-mysql-cluster) + - [Schema setup](#####-set-up-the-schema) + - [S3 bucket for zts data](####-create-s3-bucket-to-store-zts-data) + - [Generate and upload service private key and Id](#####-generate-and-upload-service-private-key-and-id) + - [Upload server X.509 cert and key](#####-upload-server-x.509-cert-and-key) + - [Upload RDS CA Certs](#####-upload-rds-ca-certs) + - [Upload truststore password](#####-upload-truststore-password) + - [Upload ZTS DB User Password](#####-upload-zts-db-user-password) + - [Upload ZMS CA Certs](#####-upload-zms-ca-certs) + - [Upload ZTS and ZMS Public keys](#####-upload-zts-and-zms-public-keys) + - [Upload Self Cert Signer Key](#####-upload-self-cert-signer-key) + - [Update the policy for S3 bucket for Audit logs](####-create-s3-bucket-for-audit-logs) + - [Update ZMS DATA BUCKET](####-update-zms-data-bucket) + - [Register ZTS Service](####-register-zts-service) + - [Edit Variables & Properties](####-edit-variables-&-properties) + - [aws_init.sh](#####-edit-aws_init.sh) + - [Edit the properties file](#####-edit-the-properties-file) + - [Database Access](######-database-access) + - [Athenz CA X.509 Certificate Issuing](######-athenz-car-x.509-certificate-issuing) + - [Truststore and Keystore Settings](######-truststore-and-keystore-settings) + - [Packer](####-packer) + - [Packer VPC setup](#####-packer-vpc-setup) + - [Build ZTS Image](#####-build-zts-image) + - [Deploy ZTS](####deploy-zts) + +## AWS Resource Setup +------------- + +### IAM role setup +-- +Create EC2 profile role for zts using cloudformation [template](https://github.com/yahoo/athenz/blob/master/aws-setup/zts-setup/cloud-formation/athens-zts-aws-roles-setup.yaml). +This template creates a role named `athenz.zts-service` + +### VPC Setup +-- +Setup VPC using the cloudformation [template](https://github.com/yahoo/athenz/blob/master/aws-setup/zts-setup/cloud-formation/athens-zts-aws-resource-setup.yaml) and giving the following mandatory parameters +- `Route53HostedZoneName` +- `Route53RecordName` +- `S3AccessLogBucketName`(Created during Zms Setup) +- `Environment` + +The other parameters are set by default. Change them as per your requirement + +*NOTE - Modifying the other defaults might require subsequent changes.* + +Following resources will be created after executing the template +1. 2 availability zones +1. Public & Private subnets for zts in each availability zone +1. Public & Private subnets for cert signer in each availability zone +1. 4 NAT gateways and elastic IPs +1. NACL's for the subnets +1. Internet gateways for all public subnets +1. Route tables for all subnets +1. Elastic load balancer +1. Route 53 DNS entry +1. ZTS Server & ELB security groups + +### RDS Setup +-- +#### Create an Aurora MySQL cluster +-- +Setup the cluster using cloudformation [template](https://github.com/yahoo/athenz/blob/master/aws-setup/zts-setup/cloud-formation/athens-zts-aws-rds-setup.yaml) by giving the below mandatory parameters + +- `Route53HostedZoneName` +- `Route53RecordName` +- `DatabaseUsername` +- `DatabasePassword` +- `Environment` + +The other parameters are set by default. Change them as per your requirement + +#### Set up the schema +-- +1. Create an instance in private subnet and login into it. +After logging in, use the following commands to connect to the cluster using Database Root Credentials + ``` + mysql -h -P 3306 -u -p + ``` +1. Copy the [zts_server.sql](https://github.com/yahoo/athenz/blob/master/servers/zts/schema/zts_server.sql) file from the Athenz Git repository onto this host and create the database using the following command + ``` + mysql -h -P 3306 -u -p < zts_server.sql + ``` +1. Create a user with full privileges on zts database created above. Foe eg. If your ZTS Server will be running on zts1.athenz.com and user to be created is `athenz-zts` having password `athenz-zts` + ``` + CREATE USER 'athenz-zts'@'zts1.athenz.com' IDENTIFIED BY 'athenz-zts'; + GRANT ALL PRIVILEGES ON zts_store TO 'athenz-zts'@'zts1.athenz.com'; + FLUSh PRIVILEGES; + ``` + +### Create S3 bucket to store zts data +-------------------------------------- + +Create S3 bucket for storing zts certificates & keys with appropriate policy as follows +``` +{ +"Version": "2012-10-17", +"Statement": [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam:::role/athenz.zts-service" + }, + "Action": "s3:GetObject", + "Resource": "arn:aws:s3::: /*" + } + ] +} +``` +Also enable Default Encryption for your bucket. + +*NOTE - athenz.zts-service is the EC2 role created using IAM template above* + +#### Generate and upload service private key and id +-- +Generate a unique private key that ZTS Server will use to sign any NTokens it issues +``` +openssl genrsa -out service_private_key 2048 +openssl rsa -in service_private_key -pubout > zts_service_x509_key_public +``` +Upload the service private key with name `service_private_key` onto the s3 bucket + +Upload the service private key id with name `service_private_key_id` onto the s3 bucket. This file just contains +the id of private key. It is not mandatory as the id defaults to `0` if not specified + +#### Upload server X.509 cert and key +-- +*NOTE - While it is still possible to generate and use a self-signed X509 certificate for ZTS Servers, +it is recommended to purchase one for your production server from a well known certificate authority. +Having such a certificate installed on your ZTS Servers will no longer require to distribute the +server's public certificate to other hosts (e.g. Hosts running ZPU).* + +- Follow the instructions provided by the Certificate Authority that you're going to purchase your certificate from, to generate your private key and Certificate Request (CSR). +- If you are using self signed certs then run the following commands: + ``` + openssl genrsa -des3 -out zts_ca_key 4096 (Create ZTS CA Key) + openssl req -x509 -new -nodes -key zts_ca_key -sha256 -days 1024 -out service_x509_ca_certs (Generate CA Cert) + openssl genrsa -out service_x509_key 2048 (Generate your private key) + openssl req -new -key service_x509_key -out service_x509_csr (Generate your CSR) + openssl x509 -req -in service_x509_csr -CA service_x509_ca_certs -CAkey zts_ca_key -CAcreateserial -out service_x509_cert -days 500 -sha256 (Generate your Certificate) + ``` +- Verify your certs + ``` + openssl x509 -in service_x509_ca_certs -text -noout + openssl x509 -in service_x509_cert -text -noout + ``` +- Once you have received your X509 certificate and key, + - Upload the certificate with on s3 bucket with name `service_x509_cert` + - Upload the private key with name `service_x509_key` + - Upload the Root CA cert with name `service_x509_ca_certs` + +#### Upload RDS CA Certs +--- +- Upload the RDS CA Certs with key `service_rds_ca_certs` + +For details on AWS RDS Certs, Please refer [RDS CERTS AWS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html) + +#### Upload truststore password +-- +- Upload password you want to use for truststore with name `service_x509_store_pwd` + +#### Upload ZTS DB User Password +-- +- Create a file containing only the password for ZTS Database user(`athenz-zts`) created above during RDS schema setup +- Upload the file to bucket with name `db_user_data` + +#### Upload ZMS CA Certs + +- Upload ZMS CA Cert with key `zms_service_x509_ca_certs`. They will be added to ZTS truststore so that ZTS can communicate securely with ZMS + +#### Upload ZTS and ZMS Public keys + +- Upload ZTS public key with name `zts_service_x509_key_public.pem ` +- Upload ZMS public key with name `zms_service_x509_key_public.pem ` + +They are required to generate athenz.conf file at `/opt/zts/conf` to include the ZTS and ZMSServer URL +and the registered public keys that the athenz client libraries and utilities will +use to establish connection and validate any data signed by the ZTS and ZMS Server: + +#### Upload Self Cert Signer Key + +You can use SelfCertSigner or have your implementation of Cert Signer. + +Refer [Certificate Signer](cert_signer.md) for full details how to implement your cert signer. + +If you are using self cert signer then + +- Generate a private key and upload it to s3 bucket with name `self_cert_signer_key` + +### Update the policy for S3 bucket for Audit logs + +Update the bucket policy for S3 bucket created for audit logs during zms setup to allow `athenz.zts-service` +role to read and write to it. + +``` +{ +"Version": "2012-10-17", +"Statement": [ + { + "Sid": "", + "Effect": "Allow", + "Principal": { + "AWS": [ + "arn:aws:iam:::role/athenz.zms-service" + "arn:aws:iam:::role/athenz.zts-service" + ] + }, + ... +] +} +``` +### Update ZMS DATA BUCKET + +- Upload zts service public key to ZMS Data Bucket with key `zts_service_x509_key_public.pem` + +### Register ZTS Service +In order for ZTS to access ZMS domain data, it must identify itself +as a registered service in ZMS. Use `zms-cli` utility to +register a new service in `sys.auth` domain. If ZMS Servers are +running with a X509 certificate from a well know certificate +authority (not a self-signed one) we don't need to reference the CA +cert like we are doing below for self signed certs. + +Login into your zms-server instance as domain admin you created during zms setup and run the below commands: + +``` +- Download ZMS CA Certs(If using self signed certs) + aws s3 cp s3:///zms_service_x509_ca_certs /tmp/zms_service_x509_ca_certs +- Download ZTS public key + aws s3 cp s3:// /zts_service_x509_key_public.pem /tmp/zts_service_x509_key_public.pem +- Register Service using zms-cli + /opt/zts/bin/zms-cli -c /tmp/service_x509_ca_certs -z -d sys.auth add-service zts 0 /tmp/zts_service_x509_key_public.pem +``` +*NOTE - Append /zms/v1 to your url in the command above* + +For e.g. If your zms server is running at https://athenz.zms.com:4443 then pass `https://athenz.zms.com:4443/zms/v1`. + +### Edit Variables & Properties +-- +#### Edit aws_init.sh +-- +Update the bucket names in `athenz/aws-setup/zts-setup/build/bin/aws_init.sh` by editing the below lines +``` +export ZTS_DATA_BUCKET_NAME="" +export ZTS_AUDIT_LOG_BUCKET_NAME="" +export ZTS_URL="" +export ZMS_URL=""" +export RDS_MASTER="" +``` +The other variables are for trust store & key store setup. We recommend to use the defaults but if you change then update the corresponding values in `athenz.properties` file discussed later. + +#### Edit the properties file +-- + +##### Database Access +-- +Modify the following settings in `zts.properties` file located at `athenz/aws-setup/zts-setup/build/conf/zts.properties` if RDS username & RDS password filename (stored on S3) are different from defaults suggested above. +``` +athenz.zts.cert_record_store_factory_class=com.yahoo.athenz.zts.cert.impl.JDBCCertRecordStoreFactory +athenz.zts.cert_jdbc_user=athenz-zts +athenz.zts.cert_jdbc_password=db_user_data +``` + +##### Athenz CA X.509 Certificate Issuing +-- + +For authenticating services using X509 certificates, ZTS Servers expect the configured cert signer factory class names in its athenz.zts.cert_signer_factory_class system property. +Self Cert Signer `com.yahoo.athenz.zts.cert.impl.SelfCertSignerFactory` is a sample implementation of cert Signer we have for development environment. +You can use SelfCertSigner or have your implementation of Cert Signer. + +If you are using self cert signer make the below changes + +The self cert signer key you uploaded in above steps has to be downloaded on the box. The default is to download +it to `/opt/zts/conf/self_cert_signer_key`. If you using the defaults, uncomment the below lines in `initialize_zts.sh` + +``` +# echo "Downloading self cert signer key" +# aws s3 cp s3://$bucket_name/self_cert_signer_key /opt/zts/conf/self_cert_signer_key +``` + +Edit the below properties in `zts.properties` file accordingly: + +``` +# athenz.zts.self_signer_private_key_fname=/opt/zts/conf/self_cert_signer_key + +#athenz.zts.self_signer_private_key_password= + +# athenz.zts.self_signer_cert_dn=C=US,ST=CA,L=Sunnyvale,O=Oath,OU=Athenz,CN=zts.aws.oath.cloud. +``` + +#### Truststore & Keystore Settings +-- +- If you modified the truststore and keystore paths and password in the `aws_init.sh` file then change the below settings in `athenz.properties` file located at `athenz/aws-setup/zts-setup/build/conf/athenz.properties` + - `athenz.ssl_key_store=/opt/zts/conf/zts_keystore.pkcs12` `//path to the keystore file that contains the server's certificate` + - `athenz.ssl_key_store_type=PKCS12` `//specifies the type for the keystore specified in the` + - `athenz.ssl_key_store_password=service_x509_store_pwd` `//S3 bucket key name for Password for the keystore specified in the athenz.ssl_key_store property` + - `athenz.ssl_trust_store=/opt/zts/conf/zts_truststore.jks` `//path to the trust store file that contains CA certificates trusted by this Jetty instance` + - `athenz.ssl_trust_store_type=JKS` `//specifies the type for the truststore specified` + - `athenz.ssl_trust_store_password=service_x509_store_pwd` `//password for the truststore` + +- Update the following in zts.properties file + - `athenz.zts.ssl_key_store=/opt/zts/conf/zts_keystore.pkcs12` `//path to the keystore file that contains the server's certificate` + - `athenz.zts.ssl_key_store_type=PKCS12` `//specifies the type for the keystore specified in the` + - `athenz.zts.ssl_key_store_password=service_x509_store_pwd` `//S3 bucket key name for Password for the keystore specified in the athenz.ssl_key_store property` + - `athenz.zts.ssl_trust_store=/opt/zts/conf/zts_truststore.jks` `//path to the trust store file that contains CA certificates trusted by this Jetty instance` + - `athenz.zts.ssl_trust_store_type=JKS` `//specifies the type for the truststore specified` + - `athenz.zts.ssl_trust_store_password=service_x509_store_pwd` `//password for the truststore` + +### Packer +-- +#### Packer VPC Setup + +Packer VPC was set during zms setup, update `packer.json` accordingly. +``` +{ + "subnet_id":"", + "vpc_id": "", + "aws_region": "", + "aws_ami_name": "zts-aws-cd-image", + "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}", + "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}", + "aws_session_token": "{{env `AWS_SESSION_TOKEN`}}", + "ssh_keypair_name":"", + "ssh_private_key_file":"", + "source_ami": "ami-02c71d7a" +} +``` + +#### Build ZTS image +-- +Build the image with packer using the following command + +``` +cd /aws-setup/zts-setup +packer build packer/aws/packer.json +``` + +### Deploy ZTS +-- +Run cloud formation [template](https://github.com/yahoo/athenz/blob/master/aws-setup/zts-setup/cloud-formation/athenz-zts-aws-instance-deployment.yaml) to bring up the zts-instances in 2 availability zones. +- The imageID parameter should be set to the image created in above step. + +The ZTS Server is now up and running. + diff --git a/docs/setup_zts.md b/docs/setup_zts.md index 2f1f4a0d5ce..fbe6157eca1 100644 --- a/docs/setup_zts.md +++ b/docs/setup_zts.md @@ -75,7 +75,7 @@ is a sample implementation of cert Signer we have for development environment. You can use SelfCertSigner or have your implementation of Cert Signer. -Refer [cert signer](cert_signer_store.md) for full details how to implement your cert signer. +Refer [Certificate Signer](cert_signer.md) for full details how to implement your cert signer. ## Start/Stop ZTS Server ------------------------ diff --git a/ui/config/default-config.js b/ui/config/default-config.js index 6e5fd6ee8ae..f0f94373363 100644 --- a/ui/config/default-config.js +++ b/ui/config/default-config.js @@ -30,7 +30,7 @@ const config = { }, userLink: function (user) { const domain = process.env.UI_SERVER || 'localhost'; - return 'https://' + domain + ':9443/athenz/domain/create/userdomain'; + return 'https://' + domain + ':443/athenz/domain/create/userdomain'; }, headerLinks: [ {title: 'Website', url: 'http://www.athenz.io', target: '_blank'}, @@ -65,7 +65,7 @@ const config = { }, userLink: function (user) { const domain = process.env.UI_SERVER || 'localhost'; - return 'https://' + domain + ':9443/athenz/domain/create/userdomain'; + return 'https://' + domain + ':443/athenz/domain/create/userdomain'; }, headerLinks: [ {title: 'Website', url: 'http://www.athenz.io', target: '_blank'}, diff --git a/ui/server.js b/ui/server.js index b8c5b40bcb1..950cd4b3033 100644 --- a/ui/server.js +++ b/ui/server.js @@ -25,4 +25,4 @@ var options = { passphrase: 'athenz' }; -https.createServer(options, app).listen(9443); +https.createServer(options, app).listen(443); diff --git a/ui/test/unit/utils/view.js b/ui/test/unit/utils/view.js index 2d3a32e996c..d8cd6a03fce 100644 --- a/ui/test/unit/utils/view.js +++ b/ui/test/unit/utils/view.js @@ -85,12 +85,12 @@ describe('view utils', function() { 'fullName': 'role', 'name': 'role', 'type': 'Regular', - 'members': [{'name': 'a'}, {'name': config.userDomain + '.b', 'userlink': 'https://localhost:9443/athenz/domain/create/userdomain'}], + 'members': [{'name': 'a'}, {'name': config.userDomain + '.b', 'userlink': 'https://localhost:443/athenz/domain/create/userdomain'}], 'auditLog': [{ 'action': 'ADD', - 'admin': {'name': config.userDomain + '.a', 'userlink': 'https://localhost:9443/athenz/domain/create/userdomain'}, + 'admin': {'name': config.userDomain + '.a', 'userlink': 'https://localhost:443/athenz/domain/create/userdomain'}, 'created': '2016-06-28T23:28:29.000Z', - 'member': {'name': config.userDomain + '.b', 'userlink': 'https://localhost:9443/athenz/domain/create/userdomain'} + 'member': {'name': config.userDomain + '.b', 'userlink': 'https://localhost:443/athenz/domain/create/userdomain'} }] } );