├── LICENSE ├── README.md ├── bootstrap ├── 01-init-bastion-host.sh ├── 02-init-internal-dns.sh ├── 03-init-openvpn.sh ├── 04-init-kops.sh ├── 05-init-kubernetes-dashboard.sh ├── alb-dns-external.yaml ├── alb-ingress-301-redirection-example.yaml ├── alb-ingress-controller.yaml ├── apache2-dashboard-init-with-http-redirect.conf ├── banner_message.txt ├── bastion-bootstrap.sh ├── cluster-autoscaler.yml ├── kops-cluster-additionalpolicies.json ├── kops-sharedvpc-iam-yamlconfig.py ├── kubernetes-dashboard.yaml ├── kubernetes-monitoring.yaml ├── purge-s3-versioned-bucket.py └── tear-down-cluster.sh ├── cfn-templates ├── latest-single-natinstance.yaml └── tc2-kuberntes-on-aws-v1.15.yaml ├── deploy-s3.sh ├── docs ├── TC2_Abstratct_production_grade_Kubernetes_deployment_on_AWS.pdf ├── k8s-fullscale.png └── k8s-small-footprint.png └── easy-openvpn ├── README.md └── keygen ├── build-ca ├── build-crl-revoke ├── build-dh ├── build-inter ├── build-key ├── build-key-embed ├── build-key-embed-commongw ├── build-key-pkcs12 ├── build-key-pkcs12-commongw ├── build-key-server ├── build-key-server-tcp-commongw ├── build-req ├── build-req-pass ├── build-ta ├── ccd ├── ccd-tcp ├── clean-all ├── client-template-embed-commongw.ovpn ├── client-template-embed.ovpn ├── client-template.commongw.p12.ovpn ├── client-template.ovpn ├── client-template.p12.ovpn ├── create-server ├── create-server-tcp-gw ├── inherit-inter ├── list-crl ├── openssl-0.9.6.cnf ├── openssl-0.9.8.cnf ├── openssl-1.0.0.cnf ├── pem-split ├── pkitool ├── revoke-client ├── server-startup-template-tcp-gw.sh ├── server-startup-template.sh ├── server-template-tcp-commongw.conf ├── server-template.conf ├── sign-req ├── vars └── whichopensslcnf /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AWS Quick Start: Production grade Kubernetes cluster deployment on AWS cloud 2 | 3 | This AWS Quick-Start ("one-click solution") based on AWS CloudFormation templates and scripts set up a flexible, secure, fault-tolerant Kubernetes cluster in AWS private VPC environment, into a configuration of your choice. The project main purposes are: quick, simple, painless, easy Kubernetes environment deployment in 10 minutes. 4 | 5 | Our solution based on Kubernetes Operations ("kops") combined with AWS CloudFormation (CFN) templates together with bootstrap scripts, help to automate the whole process. The final result is a 100% compatible Kubernetes cluster, what you can manage from either the Bastion host, via OpenVPN or using it's HTTPS API through AWS ELB endpoint. 6 | 7 | We always keep focus on security, transparency and simplicity. This guide is mainly created for developers, IT architects, administrators, and DevOps professionals who are planning to easily deploy their Kubernetes workloads on AWS. 8 | 9 | 10 | # Architecture 11 | 12 | [![N|Solid](https://raw.githubusercontent.com/totalcloudconsulting/kubernetes-aws/master/docs/k8s-small-footprint.png)](https://totalcloudconsulting.hu/en/solutions/containerization) 13 | 14 | 15 | [AWS Quick-Start Launch](https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=Total-Cloud-Kubernetes&templateURL=https://s3-eu-west-1.amazonaws.com/tc2-kubernetes/latest/cfn-templates/latest-single-natinstance.yaml ) 16 | 17 | ## Resources deployed 18 | 19 | * one new VPC: 3 private and 3 public subnets in 3 different Availability Zones, Gateway type Private Link routes to S3 and DynamoDB (free), 20 | * one self-healing Kubernetes Master instance in one Availability Zone's private subnet, 21 | * auto-scalable Node instances in AutoScaling groups, expended over all Availability Zones, 22 | * one self-healing bastion host in 1 Availability Zone's public subnet, bastion host is the NAT instance router for private subnets, 23 | * one Elastic IP Address (EIP) for bastion host, 24 | * one internal (or public: optional) ELB load balancer for HTTPS access to the Kubernetes API server, 25 | * two CloudWatch Logs group for bastion host and Kubernetes Docker pods (optional), 26 | * one Lambda function for graceful teardown with AWS SSM, 27 | * two security groups: 1 for bastion host, 1 for Kubernetes Hosts (Master and Nodes) 28 | * IAM roles for bastion hosts, K8s Nodes and Master hosts 29 | * one S3 bucket for kops state store, 30 | * one Route53 private zone for VPC (optional), 31 | * OpenVPN service with auto-generated keys on bastion host (optional) 32 | * AWS EFS mounted on bastion in all AZs 33 | * optional ALB ingress controller with external (Route53) domain management 34 | 35 | # How To build your cluster 36 | 37 | * Sign up for an AWS account at https://aws.amazon.com. then sign in with proper rights (IAM full rights are required) 38 | 39 | Create the Kubernetes cluster: 40 | 41 | [AWS Quick-Start Launch](https://console.aws.amazon.com/cloudformation/home?region=eu-west-1#/stacks/new?stackName=Total-Cloud-Kubernetes&templateURL=https://s3-eu-west-1.amazonaws.com/tc2-kubernetes/latest/cfn-templates/latest-single-natinstance.yaml ) 42 | 43 | 44 | **The cluster (via bastion host) creation lasts around 10-15 minutes, please be patient.** 45 | 46 | * Connect to your Kubernetes cluster by following the step-by-step instructions in the deployment guide. 47 | 48 | To customize your deployment, you can choose different instance types for the Kubernetes cluster and the bastion host, choose the number of worker nodes, API endpoint type, logging option, OpenVPN install, plug-ins. 49 | 50 | For detailed instructions, see the deployment guide. 51 | 52 | 53 | The cluster (via bastion host) creation lasts around 10 minutes, please be patient. 54 | 55 | **After the clutser has been created, just connect to the bastion host via SSH, the "kops", "kubectl" and "helm" commands working out-of-the box, no extras steps needed!** 56 | 57 | # Abstract paper 58 | 59 | Have a look at [this abstract paper](docs/TC2_Abstratct_production_grade_Kubernetes_deployment_on_AWS.pdf) for the high level details of this solution. 60 | 61 | # Visit us 62 | 63 | https://totalcloudconsulting.hu/en/solutions 64 | 65 | # References 66 | 67 | * Kubernetes Open-Source Documentation: https://kubernetes.io/docs/ 68 | * Calico Networking: http://docs.projectcalico.org/ 69 | * KOPS documentation: https://github.com/kubernetes/kops/blob/master/docs/aws.md , https://github.com/kubernetes/kops/tree/master/docs 70 | * Kubernetes Host OS versions: https://github.com/kubernetes/kops/blob/master/docs/images.md 71 | * OpenVPN: https://github.com/tatobi/easy-openvpn 72 | * ALB ingress controller: https://github.com/kubernetes-sigs/aws-alb-ingress-controller 73 | 74 | # Costs and licenses 75 | 76 | You are responsible for the cost of the AWS services used while running this deployment. Our project hosted under Apache 2.0 open source license. 77 | -------------------------------------------------------------------------------- /bootstrap/01-init-bastion-host.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "#################" 4 | echo "INIT-BASTION-HOST START..." 5 | 6 | S3BootstrapBucketName=${1} 7 | S3BootstrapBucketPrefix=${2} 8 | AWSRegion=${3} 9 | VPCIPv4CIDRBlock=${4} 10 | 11 | #install modified AWS Bastion bootstrap 12 | export BASTION_BOOTSTRAP_FILE=bastion-bootstrap.sh 13 | 14 | cp banner_message.txt /etc/ssh_banner 15 | 16 | main_interface=`ip r sh | grep default | awk '{print $5}'` 17 | 18 | iptables -t nat -A POSTROUTING -s ${VPCIPv4CIDRBlock} -o ${main_interface} -j MASQUERADE 19 | echo 1 > /proc/sys/net/ipv4/ip_forward 20 | 21 | sysctl -w net.ipv4.ip_forward=1 22 | echo 'net.ipv4.ip_forward = 1' | tee --append /etc/sysctl.conf 23 | 24 | echo '#!/bin/sh -e' | tee /etc/rc.local 25 | echo '' | tee --append /etc/rc.local 26 | echo "iptables -t nat -A POSTROUTING -s ${VPCIPv4CIDRBlock} -o ${main_interface} -j MASQUERADE" | tee --append /etc/rc.local 27 | echo 'exit 0' | tee --append /etc/rc.local 28 | 29 | chmod +x $BASTION_BOOTSTRAP_FILE 30 | ./$BASTION_BOOTSTRAP_FILE --banner banner_message.txt --enable true > ./bastion-bootstrap.log 2>&1 || exit 0 31 | 32 | sleep 5 33 | 34 | echo "INIT-BASTION-HOST DONE." 35 | echo "#################" 36 | exit 0 37 | -------------------------------------------------------------------------------- /bootstrap/02-init-internal-dns.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | AWSRegion=${1} 4 | VPC=${2} 5 | KubernetesAPIPublicAccess=${3} 6 | AWSCfnStackName=${4} 7 | 8 | 9 | echo "#################" 10 | echo "START INIT-INTERNAL-DNS..." 11 | 12 | randomstuff=`cat /dev/urandom | tr -dc 'a-z0-9' | head -c 8` 13 | stacklower=`echo "${AWSCfnStackName}" | tr '[:upper:]' '[:lower:]'` 14 | 15 | if [[ "${KubernetesAPIPublicAccess}" == "false" ]]; 16 | then 17 | K8sRoute53ZoneName="${stacklower}-${randomstuff}.internal" 18 | echo "K8s Internal DNS Zone name is: ${K8sRoute53ZoneName}" 19 | echo ${K8sRoute53ZoneName} > /opt/kops-state/KOPS_VPC_R53_ZONE_DNS 20 | 21 | aws route53 create-hosted-zone --name ${K8sRoute53ZoneName} --vpc VPCRegion=${AWSRegion},VPCId=${VPC} --hosted-zone-config Comment="${AWSCfnStackName}-Kubernetes",PrivateZone=true --region ${AWSRegion} --caller-reference "`date`" --output text | grep "hostedzone/" | grep "https://route53.amazonaws.com" | cut -d '/' -f 6 > /opt/kops-state/KOPS_R53_PRIVATE_HOSTED_ZONE_ID 22 | fi 23 | 24 | echo "DONE START INIT-INTERNAL-DNS." 25 | echo "#################" 26 | exit 0 27 | -------------------------------------------------------------------------------- /bootstrap/03-init-openvpn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "#################" 4 | echo "INIT-OPENVPN START..." 5 | 6 | VPCIPv4CIDRBlock=${1} 7 | VPNCACountryISOCode=${2} 8 | VPNCAProvince=${3} 9 | VPNCACity=${4} 10 | VPNCAOrganization=${5} 11 | VPNCAOrgEmail=${6} 12 | VPNCAOrgUnit=${7} 13 | VPNNumberOfPreGeneratedCerts=${8} 14 | K8sClusterName=${9} 15 | 16 | mv /opt/easy-openvpn/keygen /etc/openvpn/ 17 | cd /etc/openvpn/keygen 18 | chmod +x /etc/openvpn/keygen/* 19 | 20 | R53PrivateDNSZoneName="" 21 | if [[ -e "/opt/kops-state/KOPS_VPC_R53_ZONE_DNS" ]]; 22 | then 23 | R53PrivateDNSZoneName=`cat /opt/kops-state/KOPS_VPC_R53_ZONE_DNS` 24 | fi 25 | 26 | export openvpnvars="/etc/openvpn/keygen/vars" 27 | 28 | ip=`curl http://169.254.169.254/latest/meta-data/public-ipv4` 29 | awsdns=$(echo $VPCIPv4CIDRBlock | tr "." " " | awk '{ print $1"."$2"."$3".2" }') 30 | 31 | echo ${ip} 32 | echo ${awsdns} 33 | 34 | sed -i 's/CHANGE_SERVER_IP/'${ip}'/g' ${openvpnvars} 35 | sed -i 's/CC/'${VPNCACountryISOCode}'/g' ${openvpnvars} 36 | sed -i 's/CHANGE_PROVINCE/'${VPNCAProvince}'/g' ${openvpnvars} 37 | sed -i 's/CHANGE_CITY/'${VPNCACity}'/g' ${openvpnvars} 38 | sed -i 's/CHANGE_ORG/'${VPNCAOrganization}'/g' ${openvpnvars} 39 | sed -i 's/CHANGE_ORG_EMAIL/'${VPNCAOrgEmail}'/g' ${openvpnvars} 40 | sed -i 's/CHANGE_OU/'${VPNCAOrgUnit}'/g' ${openvpnvars} 41 | 42 | echo "push \"route $VPCIPv4CIDRBlock 255.255.0.0\"" | tee --append server-template.conf 43 | echo "push \"register-dns\"" | tee --append server-template.conf 44 | 45 | if [[ -n ${R53PrivateDNSZoneName} ]]; 46 | then 47 | echo "push \"dhcp-option DNS __REPLACE_AWS_DNS__\"" | tee --append server-template.conf 48 | echo "push \"dhcp-option DOMAIN $R53PrivateDNSZoneName\"" | tee --append server-template.conf 49 | sed -i 's/__REPLACE_AWS_DNS__/'${awsdns}'/g' server-template.conf 50 | fi 51 | 52 | ./create-server 53 | service openvpn@server start 54 | systemctl enable openvpn@server 55 | 56 | #set options in client file for tunnelblick 57 | echo "dhcp-option DNS ${awsdns}" | tee --append client-template-embed.ovpn 58 | echo "dhcp-option DOMAIN $R53PrivateDNSZoneName" | tee --append client-template-embed.ovpn 59 | 60 | i=1 61 | while [[ "$i" -le "${VPNNumberOfPreGeneratedCerts}" ]]; 62 | do 63 | ./build-key-embed "K8s.OVPNkey.${K8sClusterName}.${i}.org"; 64 | cp /etc/openvpn/keys/K8s.OVPNkey.${K8sClusterName}.${i}.org/K8s.OVPNkey.${K8sClusterName}.${i}.org.ovpn /opt/openvpn-keys/; 65 | i=$((i + 1)) 66 | done 67 | 68 | chown ubuntu:ubuntu /opt/openvpn-keys/* 69 | 70 | echo "INIT-OPENVPN DONE." 71 | echo "#################" 72 | 73 | exit 0 74 | 75 | -------------------------------------------------------------------------------- /bootstrap/04-init-kops.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | AWSRegion=${1} 4 | AWSCfnStackName=${2} 5 | Ec2K8sMasterInstanceType=${3} 6 | Ec2K8sNodeInstanceType=${4} 7 | Ec2K8sNodeCapacityMin=${5} 8 | Ec2K8sNodeCapacityMax=${6} 9 | Ec2EBSK8sDiskSizeGb=${7} 10 | Ec2K8sAMIOsType=${8} 11 | Ec2K8sMultiAZMaster=${9} 12 | VPC=${10} 13 | NetworkCIDR=${11} 14 | PrivateSubnet1=${12} 15 | PrivateSubnet2=${13} 16 | PrivateSubnet3=${14} 17 | PublicSubnet1=${15} 18 | PublicSubnet2=${16} 19 | PublicSubnet3=${17} 20 | K8sMasterAndNodeSecurityGroup=${18} 21 | S3BootstrapBucketName=${18} 22 | S3BootstrapBucketPrefix=${20} 23 | KubernetesDashboard=${21} 24 | KubernetesALBIngressController=${22} 25 | KubernetesClusterAutoscaler=${23} 26 | KubernetesAPIPublicAccess=${24} 27 | KubernetesExternalDNSPlugin=${25} 28 | KubernetesExternalDNSName=${26} 29 | KubernetesExternalDNSTXTSelector=${27} 30 | KOPSReleaseVersion=${28} 31 | KUBECTLReleaseVersion=${29} 32 | HELMReleaseVersion=${30} 33 | FORCED_AMI_ID=${31} 34 | NODES_SPOT_PRICE="0.0" 35 | 36 | echo "#################" 37 | echo "START INIT-KOPS." 38 | 39 | AWSCfnStackName=`echo "${AWSCfnStackName}" | tr '[:upper:]' '[:lower:]'` 40 | randomstuff=`cat /dev/urandom | tr -dc 'a-z0-9' | head -c 8` 41 | 42 | 43 | #sync kops, k8s binaries 44 | aws s3 sync s3://${S3BootstrapBucketName}/${S3BootstrapBucketPrefix}/bin/ /usr/local/bin/ --region ${AWSRegion} --quiet 45 | 46 | if [[ ! -e /usr/local/bin/kops ]]; 47 | then 48 | echo "Download latest KOPS..."; 49 | wget -O kops https://github.com/kubernetes/kops/releases/download/${KOPSReleaseVersion}/kops-linux-amd64 --no-verbose 50 | sudo mv ./kops /usr/local/bin/ 51 | fi 52 | 53 | if [[ ! -e /usr/local/bin/kubectl ]]; 54 | then 55 | echo "Download latest KUBECTL..."; 56 | wget -O kubectl https://storage.googleapis.com/kubernetes-release/release/v${KUBECTLReleaseVersion}/bin/linux/amd64/kubectl --no-verbose 57 | mv ./kubectl /usr/local/bin/kubectl 58 | fi 59 | 60 | if [[ ! -e /usr/local/bin/helm ]]; 61 | then 62 | echo "Download latest HELM..."; 63 | wget -O helm.tar.gz https://storage.googleapis.com/kubernetes-helm/helm-v${HELMReleaseVersion}-linux-amd64.tar.gz --no-verbose 64 | tar -xf helm.tar.gz 65 | mv ./linux-amd64/helm /usr/local/bin/helm 66 | fi 67 | 68 | chmod +x /usr/local/bin/* 69 | 70 | 71 | #get zones 72 | subnetzone1=`aws ec2 describe-subnets --subnet-ids ${PrivateSubnet1} --output text --region ${AWSRegion} | grep 'SUBNETS' | awk '{print $3}'` 73 | echo "Zone1: ${subnetzone1}" 74 | 75 | subnetzone2=`aws ec2 describe-subnets --subnet-ids ${PrivateSubnet2} --output text --region ${AWSRegion} | grep 'SUBNETS' | awk '{print $3}'` 76 | echo "Zone2: ${subnetzone2}" 77 | 78 | #master_zones 79 | master_zones="--master-zones=${subnetzone1},${subnetzone2}" 80 | 81 | #node zones 82 | node_zones="--zones=${subnetzone1},${subnetzone2}" 83 | 84 | if [[ -n ${PrivateSubnet3} ]]; 85 | then 86 | subnetzone3=`aws ec2 describe-subnets --subnet-ids ${PrivateSubnet3} --output text --region ${AWSRegion} | grep 'SUBNETS' | awk '{print $3}'` 87 | if [[ -n ${subnetzone3} ]]; 88 | then 89 | echo "Zone3: ${subnetzone3}" 90 | master_zones="--master-zones=${subnetzone1},${subnetzone2},${subnetzone3}" 91 | node_zones="--zones=${subnetzone1},${subnetzone2},${subnetzone3}" 92 | fi 93 | fi 94 | 95 | K8sRoute53ZoneName="${AWSCfnStackName}.k8s.local" 96 | K8sClusterName=${K8sRoute53ZoneName} 97 | if [[ -e "/opt/kops-state/KOPS_VPC_R53_ZONE_DNS" ]]; 98 | then 99 | K8sRoute53ZoneName=`cat /opt/kops-state/KOPS_VPC_R53_ZONE_DNS` 100 | K8sRoute53ZoneName=`echo "${K8sRoute53ZoneName}" | tr '[:upper:]' '[:lower:]'` 101 | K8sClusterName=${K8sRoute53ZoneName} 102 | else 103 | echo "ERROR: no internal zone found, using local gossip based dns: ${K8sRoute53ZoneName}" 104 | fi 105 | 106 | echo "K8sRoute53ZoneName: ${K8sRoute53ZoneName}" 107 | echo "K8sClusterName: ${K8sClusterName}" 108 | 109 | #create s3 bucket 110 | if [[ ! -e s3-kops-state.txt ]]; 111 | then 112 | s3bucket="kops-state-${AWSCfnStackName}-${randomstuff}" 113 | echo "Create bucket: ${s3bucket}" 114 | echo ${s3bucket} > s3-kops-state.txt 115 | else 116 | s3bucket=`cat s3-kops-state.txt` 117 | fi 118 | 119 | echo "KOPS state S3 bucket: ${s3bucket}" 120 | 121 | export KOPS_STATE_STORE=s3://${s3bucket} 122 | 123 | echo ${VPC} >> /opt/kops-state/KOPS_VPC 124 | 125 | echo ${KOPS_STATE_STORE} > /opt/kops-state/KOPS_STATE_STORE 126 | echo ${PrivateSubnet1} > /opt/kops-state/KOPS_PRIVATE_SUBNETS 127 | echo ${PrivateSubnet2} >> /opt/kops-state/KOPS_PRIVATE_SUBNETS 128 | 129 | if [[ -n ${PrivateSubnet3} ]]; 130 | then 131 | echo ${PrivateSubnet3} >> /opt/kops-state/KOPS_PRIVATE_SUBNETS 132 | fi 133 | echo ${K8sMasterAndNodeSecurityGroup} > /opt/kops-state/KOPS_SECURITY_GROUP 134 | 135 | echo ${PublicSubnet1} >> /opt/kops-state/KOPS_PUBLIC_SUBNETS 136 | echo ${PublicSubnet2} >> /opt/kops-state/KOPS_PUBLIC_SUBNETS 137 | echo ${PublicSubnet3} >> /opt/kops-state/KOPS_PUBLIC_SUBNETS 138 | 139 | #create kops state bucket 140 | if [[ "${AWSRegion}" == "us-east-1" ]]; 141 | then 142 | aws s3api create-bucket --bucket ${s3bucket} --region ${AWSRegion} 143 | else 144 | aws s3api create-bucket --bucket ${s3bucket} --region ${AWSRegion} --create-bucket-configuration LocationConstraint=${AWSRegion} 145 | fi 146 | 147 | #switch on kops state bucket versioning 148 | aws s3api put-bucket-versioning --bucket ${s3bucket} --versioning-configuration Status=Enabled --region ${AWSRegion} 149 | 150 | #public key for kops 151 | pkey=`head -n1 /home/ubuntu/.ssh/authorized_keys` 152 | echo ${pkey} > id_rsa.pub 153 | chmod 600 id_rsa.pub 154 | 155 | 156 | #defione image for nodes 157 | #Debian Jessie is the default if no option 158 | k8s_ami="" 159 | host_ssl_certpath="/etc/ssl/certs/ca-certificates.crt" 160 | host_ssl_certdir="/etc/ssl/certs" 161 | 162 | 163 | if [ "${Ec2K8sAMIOsType}" == "Ubuntu-1604-LTS" ]; 164 | then 165 | ami_ubuntu=`aws ec2 describe-images --owners 099720109477 --filters Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server* --query 'Images[*].[ImageId,CreationDate]' --output text --region ${AWSRegion} | sort -k2 -r | head -n1 | awk '{print $1}'` 166 | k8s_ami="--image=${ami_ubuntu}" 167 | fi 168 | 169 | if [ "${Ec2K8sAMIOsType}" == "Ubuntu-1804-LTS" ]; 170 | then 171 | ami_ubuntu=`aws ec2 describe-images --owners 099720109477 --filters Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-xenial-18.04-amd64-server* --query 'Images[*].[ImageId,CreationDate]' --output text --region ${AWSRegion} | sort -k2 -r | head -n1 | awk '{print $1}'` 172 | k8s_ami="--image=${ami_ubuntu}" 173 | fi 174 | 175 | if [ "${Ec2K8sAMIOsType}" == "AmazonLinux2" ]; 176 | then 177 | ami_ubuntu=`aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" "Name=architecture,Values=x86_64" "Name=root-device-type,Values=ebs" --query 'Images[*].[ImageId,CreationDate]' --output text --region ${AWSRegion} | sort -k2 -r | head -n1 | awk '{print $1}'` 178 | k8s_ami="--image=${ami_ubuntu}" 179 | host_ssl_certpath="/etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt" 180 | host_ssl_certdir="/etc/pki/ca-trust/extracted/pem" 181 | fi 182 | 183 | if [ "${Ec2K8sAMIOsType}" == "CentOS-7" ]; 184 | then 185 | ami_centos=`aws ec2 describe-images --owners 410186602215 --filters "Name=virtualization-type,Values=hvm" "Name=name,Values=CentOS Linux 7 x86_64 HVM EBS*" --query 'Images[*].[ImageId,CreationDate]' --output text --region ${AWSRegion} | sort -k2 -r | head -n1 | awk '{print $1}'` 186 | k8s_ami="--image=${ami_centos}" 187 | host_ssl_certpath="/etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt" 188 | host_ssl_certdir="/etc/pki/ca-trust/extracted/pem" 189 | fi 190 | 191 | if [ "${Ec2K8sAMIOsType}" == "RHEL-7" ]; 192 | then 193 | ami_rhel7=`aws ec2 describe-images --owner=309956199498 --filters "Name=virtualization-type,Values=hvm" "Name=name,Values=RHEL-7.*" --query 'Images[*].[ImageId,CreationDate]' --output text --region ${AWSRegion} | sort -k2 -r | head -n1 | awk '{print $1}'` 194 | k8s_ami="--image=${ami_rhel7}" 195 | host_ssl_certpath="/etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt" 196 | host_ssl_certdir="/etc/pki/ca-trust/extracted/pem" 197 | fi 198 | 199 | if [[ -n ${FORCED_AMI_ID} ]]; 200 | then 201 | echo "FORCE AMI ID TO USE: ${FORCED_AMI_ID}" 202 | k8s_ami="--image=${FORCED_AMI_ID}" 203 | fi 204 | 205 | echo "Kubernetes Cluster AMI: ${k8s_ami}" 206 | 207 | #internal / external API 208 | api_lb_type="--api-loadbalancer-type=internal" 209 | dns_zone="--dns-zone=${K8sRoute53ZoneName}" 210 | dns="--dns=private" 211 | if [[ "${KubernetesAPIPublicAccess}" == "true" ]]; 212 | then 213 | echo "K8s API LB is Public, using Gossip DNS configuration ..." 214 | api_lb_type="--api-loadbalancer-type=public" 215 | dns_zone="" 216 | dns="" 217 | K8sClusterName="${AWSCfnStackName}.k8s.local" 218 | fi 219 | 220 | # set env variables 221 | echo ${K8sClusterName} > /opt/kops-state/KOPS_CLUSTER_NAME 222 | echo "INIT KOPS with: K8sClusterName: ${K8sClusterName}" 223 | 224 | echo "export KOPS_STATE_STORE=${KOPS_STATE_STORE}" >> /etc/bashrc 225 | echo "export NAME=${K8sClusterName}" >> /etc/bashrc 226 | 227 | echo "export KOPS_STATE_STORE=${KOPS_STATE_STORE}" >> /home/ubuntu/.bashrc 228 | echo "export NAME=${K8sClusterName}" >> /home/ubuntu/.bashrc 229 | 230 | echo "export KOPS_STATE_STORE=${KOPS_STATE_STORE}" >> /root/.bashrc 231 | echo "export NAME=${K8sClusterName}" >> /root/.bashrc 232 | 233 | 234 | #tag instance 235 | instance_id=`curl http://169.254.169.254/latest/meta-data/instance-id` 236 | aws ec2 create-tags --resources ${instance_id} --tags Key=KOPS-state-store-bucket,Value=${KOPS_STATE_STORE} --region ${AWSRegion} 237 | 238 | #create kops config 239 | if [ "${Ec2K8sMultiAZMaster}" == "true" ]; 240 | then 241 | kops create cluster \ 242 | --name="${K8sClusterName}" \ 243 | --cloud-labels="Name=${K8sClusterName}" \ 244 | ${dns_zone} \ 245 | ${dns} \ 246 | ${node_zones} \ 247 | ${master_zones} \ 248 | --master-count=3 \ 249 | --state="s3://${s3bucket}" \ 250 | --topology="private" \ 251 | --networking="calico" \ 252 | --node-count="${Ec2K8sNodeCapacityMin}" \ 253 | --node-size="${Ec2K8sNodeInstanceType}" \ 254 | --master-size="${Ec2K8sMasterInstanceType}" \ 255 | --vpc="${VPC}" \ 256 | --cloud="aws" \ 257 | --ssh-public-key="id_rsa.pub" \ 258 | ${k8s_ami} \ 259 | --associate-public-ip="false" \ 260 | ${api_lb_type} \ 261 | --network-cidr="${NetworkCIDR}" \ 262 | --master-security-groups="${K8sMasterAndNodeSecurityGroup}" \ 263 | --node-security-groups="${K8sMasterAndNodeSecurityGroup}" \ 264 | --master-volume-size="${Ec2EBSK8sDiskSizeGb}" \ 265 | --node-volume-size="${Ec2EBSK8sDiskSizeGb}" \ 266 | --authorization="RBAC" \ 267 | --dry-run \ 268 | --output="yaml" > /opt/kops-config/${K8sClusterName}.yaml || exit 1 269 | else 270 | kops create cluster \ 271 | --name="${K8sClusterName}" \ 272 | --cloud-labels="Name=${K8sClusterName}" \ 273 | ${dns_zone} \ 274 | ${dns} \ 275 | ${node_zones} \ 276 | --master-count=1 \ 277 | --state="s3://${s3bucket}" \ 278 | --topology="private" \ 279 | --networking="calico" \ 280 | --node-count="${Ec2K8sNodeCapacityMin}" \ 281 | --node-size="${Ec2K8sNodeInstanceType}" \ 282 | --master-size="${Ec2K8sMasterInstanceType}" \ 283 | --vpc="${VPC}" \ 284 | --cloud="aws" \ 285 | --ssh-public-key="id_rsa.pub" \ 286 | ${k8s_ami} \ 287 | --associate-public-ip="false" \ 288 | ${api_lb_type} \ 289 | --network-cidr="${NetworkCIDR}" \ 290 | --master-security-groups="${K8sMasterAndNodeSecurityGroup}" \ 291 | --node-security-groups="${K8sMasterAndNodeSecurityGroup}" \ 292 | --master-volume-size="${Ec2EBSK8sDiskSizeGb}" \ 293 | --node-volume-size="${Ec2EBSK8sDiskSizeGb}" \ 294 | --authorization="RBAC" \ 295 | --dry-run \ 296 | --output="yaml" > /opt/kops-config/${K8sClusterName}.yaml || exit 1 297 | fi 298 | 299 | #apply subnet and policy mod 300 | python kops-sharedvpc-iam-yamlconfig.py ${AWSRegion} /opt/kops-config/${K8sClusterName}.yaml kops-cluster-additionalpolicies.json /opt/kops-config/${K8sClusterName}.MOD.yaml ${NODES_SPOT_PRICE} ${Ec2K8sNodeCapacityMax} 301 | 302 | #check existing modified config 303 | if [[ ! -e "/opt/kops-config/${K8sClusterName}.MOD.yaml" ]]; 304 | then 305 | echo "ERROR: missing Kops config file!" 306 | exit 1 307 | fi 308 | 309 | #create k8s cluster config 310 | kops create -f /opt/kops-config/${K8sClusterName}.MOD.yaml 311 | 312 | #create k8s secret with Ubuntu SSH key 313 | kops create secret --name ${K8sClusterName} sshpublickey admin -i id_rsa.pub 314 | 315 | #apply cluster changes 316 | kops update cluster ${K8sClusterName} --yes 317 | 318 | #wait for cluster ready 319 | k8s_done="" 320 | k8s_successful=1 321 | 322 | #init kops environment on Bastion host 323 | export HOME=/opt 324 | cd $HOME 325 | kops export kubecfg ${K8sClusterName} 326 | 327 | mkdir -p /home/ubuntu/.kube 328 | cp $HOME/.kube/config /home/ubuntu/.kube/ 329 | 330 | for i in {1..90}; 331 | do 332 | clusterstate=`kops validate cluster | egrep -i "is not healthy|is ready" | grep -v grep`; 333 | if [[ -n ${clusterstate} ]]; 334 | then 335 | echo ${clusterstate}; 336 | k8s_done="OK"; 337 | k8s_successful=0; 338 | break; 339 | else 340 | echo $i; 341 | sleep 10; 342 | fi 343 | done 344 | 345 | sleep 10 346 | 347 | #init kops environment on Bastion host 348 | export HOME=/opt 349 | cd $HOME 350 | kops export kubecfg ${K8sClusterName} 351 | 352 | 353 | mkdir -p /home/ubuntu/.kube 354 | cp $HOME/.kube/config /home/ubuntu/.kube/ 355 | 356 | mkdir -p /root/.kube 357 | cp $HOME/.kube/config /root/.kube/ 358 | 359 | chown -R ubuntu:ubuntu /home/ubuntu 360 | chown -R ubuntu:ubuntu /opt 361 | chmod -R og+rX /opt 362 | 363 | if [[ ! -n ${k8s_done} ]]; 364 | then 365 | echo "########################" 366 | echo "ERROR CLUSTER DOES NOT RUNNING HEALTHY!" 367 | echo "########################" 368 | else 369 | echo "########################" 370 | echo "K8S CLUSTER IS RUNNING." 371 | echo "########################" 372 | fi 373 | 374 | ## workaround for RHEL/CentOS/Amazonlinux host + Calico + Multi-AZ nezworking / k8s-ec2-srcdst 375 | if [ "${Ec2K8sAMIOsType}" == "CentOS-7" ] || [ "${Ec2K8sAMIOsType}" == "RHEL-7" ] || [ "${Ec2K8sAMIOsType}" == "AmazonLinux2" ]; 376 | then 377 | echo "APPLY k8s-ec2-srcdst pathch..." 378 | kubectl patch deployment k8s-ec2-srcdst --namespace kube-system -p '{"apiVersion":"extensions/v1beta1","kind":"Deployment","metadata":{"annotations":{},"labels":{"k8s-app":"k8s-ec2-srcdst","role.kubernetes.io/networking":"1"},"name":"k8s-ec2-srcdst","namespace":"kube-system"},"spec":{"replicas":1,"selector":{"matchLabels":{"k8s-app":"k8s-ec2-srcdst"}},"template":{"metadata":{"annotations":{"scheduler.alpha.kubernetes.io/critical-pod":""},"labels":{"k8s-app":"k8s-ec2-srcdst","role.kubernetes.io/networking":"1"}},"spec":{"containers":[{"imagePullPolicy":"Always","name":"k8s-ec2-srcdst","resources":{"requests":{"cpu":"10m","memory":"64Mi"}},"volumeMounts":[{"mountPath":"/etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt","name":"ssl-certs","readOnly":true}]}],"hostNetwork":true,"nodeSelector":{"node-role.kubernetes.io/master":""},"serviceAccountName":"k8s-ec2-srcdst","tolerations":[{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"},{"key":"CriticalAddonsOnly","operator":"Exists"}],"volumes":[{"hostPath":{"path":"/etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt"},"name":"ssl-certs"}]}}}}' 379 | fi 380 | 381 | #Enable legacy authorization mode 382 | kubectl create clusterrolebinding permissive-binding --clusterrole=cluster-admin --user=admin --user=kubelet --group=system:serviceaccounts 383 | 384 | for i in {1..120}; 385 | do 386 | clusterstate=`kops validate cluster | grep -i "is ready" | grep -v grep`; 387 | if [[ -n ${clusterstate} ]]; 388 | then 389 | echo ${clusterstate}; 390 | k8s_done="OK"; 391 | k8s_successful=0; 392 | break; 393 | else 394 | echo $i; 395 | sleep 10; 396 | fi 397 | done 398 | 399 | 400 | ####################### 401 | # KOPS Addons 402 | ####################### 403 | echo "########################" 404 | echo "Install addons ..." 405 | echo "########################" 406 | 407 | cd /opt/bastion-init/ 408 | 409 | sleep 5 410 | 411 | # Kubernetes Cluster Autoscaler 412 | if [ "${KubernetesClusterAutoscaler}" == "true" ]; 413 | then 414 | echo "Install K8s Cluster Autoscaler ..." 415 | 416 | #RH certpath: /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt 417 | 418 | CLOUD_PROVIDER=aws 419 | IMAGE=gcr.io/google-containers/cluster-autoscaler:v1.3.5 420 | MIN_NODES=${Ec2K8sNodeCapacityMin} 421 | MAX_NODES=${Ec2K8sNodeCapacityMax} 422 | AWS_REGION=${AWSRegion} 423 | GROUP_NAME="nodes.${K8sClusterName}" 424 | SSL_CERT_PATH=${host_ssl_certpath} 425 | 426 | addon=cluster-autoscaler.yml 427 | 428 | sed -i -e "s@{{CLOUD_PROVIDER}}@${CLOUD_PROVIDER}@g" "${addon}" 429 | sed -i -e "s@{{IMAGE}}@${IMAGE}@g" "${addon}" 430 | sed -i -e "s@{{MIN_NODES}}@${MIN_NODES}@g" "${addon}" 431 | sed -i -e "s@{{MAX_NODES}}@${MAX_NODES}@g" "${addon}" 432 | sed -i -e "s@{{GROUP_NAME}}@${GROUP_NAME}@g" "${addon}" 433 | sed -i -e "s@{{AWS_REGION}}@${AWS_REGION}@g" "${addon}" 434 | sed -i -e "s@{{SSL_CERT_PATH}}@${SSL_CERT_PATH}@g" "${addon}" 435 | 436 | kubectl apply -f ${addon} 437 | fi 438 | 439 | # Kubernetes ALB ingress controller 440 | if [ "${KubernetesALBIngressController}" == "true" ]; 441 | then 442 | echo "Install K8s ALB ingress controller ..." 443 | 444 | addon=alb-ingress-controller.yaml 445 | sed -i 's/__REPLACE_AWS_REGION__/'${AWSRegion}'/g' ${addon} 446 | sed -i 's/__REPLACE_K8S_CLUSTER_NAME__/'${K8sClusterName}'/g' ${addon} 447 | sed -i 's/__REPLACE_VPC_ID__/'${VPC}'/g' ${addon} 448 | 449 | kubectl apply -f ${addon} 450 | fi 451 | 452 | 453 | # kubernetes dashboard 454 | if [ "${KubernetesDashboard}" == "true" ]; 455 | then 456 | echo "Install monitoring plugins ( influxDB, grafana, heapster ) ..." 457 | addon=kubernetes-monitoring.yaml 458 | 459 | SSL_CERT_DIR=${host_ssl_certdir} 460 | sed -i -e "s@{{SSL_CERT_DIR}}@${SSL_CERT_DIR}@g" "${addon}" 461 | kubectl apply -f ${addon} 462 | 463 | echo "Install Kubernetes Dashboard ..." 464 | kubectl apply -f kubernetes-dashboard.yaml 465 | 466 | fi 467 | 468 | # kubernetes external DNS plugin 469 | if [ "${KubernetesExternalDNSPlugin}" == "true" ]; 470 | then 471 | echo "Install external-dns plugin ..." 472 | addon=alb-dns-external.yaml 473 | 474 | if [[ ! -n ${KubernetesExternalDNSName} ]]; 475 | then 476 | KubernetesExternalDNSName=${K8sClusterName} 477 | fi 478 | 479 | sed -i 's/__REPLACE_DNS_NAME__/'${KubernetesExternalDNSName}'/g' ${addon} 480 | sed -i 's/__REPLACE_ZONE_TXT_ID__/'${KubernetesExternalDNSTXTSelector}'/g' ${addon} 481 | kubectl apply -f ${addon} 482 | 483 | fi 484 | 485 | #final kops validation 486 | for i in {1..120}; 487 | do 488 | clusterstate=`kops validate cluster | grep "is ready" | grep -v grep`; 489 | if [[ -n ${clusterstate} ]]; 490 | then 491 | echo ${clusterstate}; 492 | k8s_done="OK"; 493 | k8s_successful=0; 494 | break; 495 | else 496 | echo $i; 497 | sleep 10; 498 | fi 499 | done 500 | 501 | for _ in {1..180}; 502 | do 503 | daskstatus=`kubectl get pods --all-namespaces | grep "ContainerCreating"` 504 | if [[ -n ${daskstatus} ]]; 505 | then 506 | echo "Waiting UP ALL CONTAINERS ..."; 507 | sleep 10; 508 | continue; 509 | else 510 | echo "Kubernetes IS UP!" 511 | break; 512 | fi 513 | done 514 | 515 | echo "Kubernetes clutser is running." 516 | 517 | echo "########################" 518 | echo "DONE INIT-KOPS. EXIT ${k8s_successful}" 519 | echo "########################" 520 | exit ${k8s_successful} 521 | -------------------------------------------------------------------------------- /bootstrap/05-init-kubernetes-dashboard.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | KubernetesDashboardUsername=${1} 4 | KubernetesDashboardPassword=${2} 5 | 6 | echo "#################" 7 | echo "START INIT-DASHBOARD." 8 | 9 | su ubuntu -c "nohup kubectl proxy > /dev/null 2>&1 &" 10 | 11 | echo "*/5 * * * * ubuntu nohup kubectl proxy > /dev/null 2>&1 &" | tee --append /etc/crontab 12 | 13 | apt-get -y install apache2 fail2ban 14 | 15 | a2enmod proxy 16 | a2enmod proxy_http 17 | a2enmod headers 18 | a2enmod rewrite 19 | 20 | service apache2 restart 21 | 22 | echo "${KubernetesDashboardPassword}" | htpasswd -i -c /opt/htpasswd-dashboard ${KubernetesDashboardUsername} 23 | 24 | cat <<'EOF' > /etc/apache2/sites-available/000-default.conf 25 | 26 | ServerAdmin webmaster@localhost 27 | DocumentRoot /var/www 28 | ProxyRequests Off 29 | ProxyPreserveHost Off 30 | 31 | AllowEncodedSlashes NoDecode 32 | 33 | 34 | AuthType Basic 35 | AuthName "Kubernetes Dashboard" 36 | AuthBasicProvider file 37 | AuthUserFile "/opt/htpasswd-dashboard" 38 | Require valid-user 39 | 40 | 41 | RequestHeader unset Authorization 42 | 43 | Redirect "/ui" /api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/overview?namespace=_all 44 | ProxyPass /ui ! 45 | 46 | ProxyPass / http://127.0.0.1:8001/ nocanon 47 | ProxyPassReverse / http://127.0.0.1:8001/ 48 | CustomLog ${APACHE_LOG_DIR}/access.log combined 49 | 50 | EOF 51 | 52 | service apache2 restart 53 | 54 | TOKEN=`su ubuntu -c 'kubectl get secret $(kubectl get serviceaccount kubernetes-dashboard -n kube-system -o jsonpath="{.secrets[0].name}") -n kube-system -o jsonpath="{.data.token}"' | base64 --decode` 55 | 56 | echo ${TOKEN} > /opt/kubernetes-dashboard-auth-token 57 | 58 | echo "########################" 59 | echo "DONE INIT-DASHBOARD. EXIT 0" 60 | echo "########################" 61 | exit 0 62 | -------------------------------------------------------------------------------- /bootstrap/alb-dns-external.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: external-dns 5 | --- 6 | apiVersion: rbac.authorization.k8s.io/v1beta1 7 | kind: ClusterRole 8 | metadata: 9 | name: external-dns 10 | rules: 11 | - apiGroups: [""] 12 | resources: ["services"] 13 | verbs: ["get","watch","list"] 14 | - apiGroups: [""] 15 | resources: ["pods"] 16 | verbs: ["get","watch","list"] 17 | - apiGroups: ["extensions"] 18 | resources: ["ingresses"] 19 | verbs: ["get","watch","list"] 20 | - apiGroups: [""] 21 | resources: ["nodes"] 22 | verbs: ["list"] 23 | --- 24 | apiVersion: rbac.authorization.k8s.io/v1beta1 25 | kind: ClusterRoleBinding 26 | metadata: 27 | name: external-dns-viewer 28 | roleRef: 29 | apiGroup: rbac.authorization.k8s.io 30 | kind: ClusterRole 31 | name: external-dns 32 | subjects: 33 | - kind: ServiceAccount 34 | name: external-dns 35 | namespace: default 36 | --- 37 | apiVersion: extensions/v1beta1 38 | kind: Deployment 39 | metadata: 40 | name: external-dns 41 | spec: 42 | strategy: 43 | type: Recreate 44 | template: 45 | metadata: 46 | labels: 47 | app: external-dns 48 | spec: 49 | serviceAccountName: external-dns 50 | containers: 51 | - name: external-dns 52 | image: registry.opensource.zalan.do/teapot/external-dns:latest 53 | args: 54 | - --source=service 55 | - --source=ingress 56 | - --domain-filter=__REPLACE_DNS_NAME__ 57 | - --provider=aws 58 | - --policy=sync 59 | - --registry=txt 60 | - --txt-owner-id=__REPLACE_ZONE_TXT_ID__ 61 | -------------------------------------------------------------------------------- /bootstrap/alb-ingress-301-redirection-example.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Ingress 3 | metadata: 4 | annotations: 5 | alb.ingress.kubernetes.io/actions.redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "StatusCode": "HTTP_301", "Port": "443"}}' 6 | alb.ingress.kubernetes.io/certificate-arn: arn:***** 7 | alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80, "HTTPS": 443}]' 8 | alb.ingress.kubernetes.io/scheme: internet-facing 9 | alb.ingress.kubernetes.io/security-groups: sg-******* 10 | alb.ingress.kubernetes.io/successCodes: 200,301,302,303,401,403,404,405 11 | labels: 12 | run: aws-elb-test-ingress 13 | name: aws-elb-test-ingress 14 | spec: 15 | rules: 16 | - http: 17 | paths: 18 | - backend: 19 | serviceName: redirect 20 | servicePort: use-annotation 21 | path: /* 22 | - host: kubermetes-service.example.com 23 | http: 24 | paths: 25 | - backend: 26 | serviceName: kubermetes-service-1-name 27 | servicePort: 80 28 | path: /* 29 | - host: kubermetes-service-2.example.com 30 | http: 31 | paths: 32 | - backend: 33 | serviceName: kubermetes-service-2-name 34 | servicePort: 80 35 | path: /* 36 | -------------------------------------------------------------------------------- /bootstrap/alb-ingress-controller.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: alb-ingress-controller 7 | name: alb-ingress-controller 8 | rules: 9 | - apiGroups: 10 | - "" 11 | - extensions 12 | resources: 13 | - configmaps 14 | - endpoints 15 | - events 16 | - ingresses 17 | - ingresses/status 18 | - services 19 | verbs: 20 | - create 21 | - get 22 | - list 23 | - update 24 | - watch 25 | - patch 26 | - apiGroups: 27 | - "" 28 | - extensions 29 | resources: 30 | - nodes 31 | - pods 32 | - secrets 33 | - services 34 | - namespaces 35 | verbs: 36 | - get 37 | - list 38 | - watch 39 | --- 40 | apiVersion: rbac.authorization.k8s.io/v1 41 | kind: ClusterRoleBinding 42 | metadata: 43 | labels: 44 | app.kubernetes.io/name: alb-ingress-controller 45 | name: alb-ingress-controller 46 | roleRef: 47 | apiGroup: rbac.authorization.k8s.io 48 | kind: ClusterRole 49 | name: alb-ingress-controller 50 | subjects: 51 | - kind: ServiceAccount 52 | name: alb-ingress-controller 53 | namespace: kube-system 54 | --- 55 | apiVersion: v1 56 | kind: ServiceAccount 57 | metadata: 58 | labels: 59 | app.kubernetes.io/name: alb-ingress-controller 60 | name: alb-ingress-controller 61 | namespace: kube-system 62 | --- 63 | 64 | # Application Load Balancer (ALB) Ingress Controller Deployment Manifest. 65 | # This manifest details sensible defaults for deploying an ALB Ingress Controller. 66 | # GitHub: https://github.com/kubernetes-sigs/aws-alb-ingress-controller 67 | apiVersion: apps/v1 68 | kind: Deployment 69 | metadata: 70 | labels: 71 | app.kubernetes.io/name: alb-ingress-controller 72 | name: alb-ingress-controller 73 | # Namespace the ALB Ingress Controller should run in. Does not impact which 74 | # namespaces it's able to resolve ingress resource for. For limiting ingress 75 | # namespace scope, see --watch-namespace. 76 | namespace: kube-system 77 | spec: 78 | selector: 79 | matchLabels: 80 | app.kubernetes.io/name: alb-ingress-controller 81 | template: 82 | metadata: 83 | labels: 84 | app.kubernetes.io/name: alb-ingress-controller 85 | spec: 86 | containers: 87 | - name: alb-ingress-controller 88 | args: 89 | # Limit the namespace where this ALB Ingress Controller deployment will 90 | # resolve ingress resources. If left commented, all namespaces are used. 91 | # - --watch-namespace=your-k8s-namespace 92 | 93 | # Setting the ingress-class flag below ensures that only ingress resources with the 94 | # annotation kubernetes.io/ingress.class: "alb" are respected by the controller. You may 95 | # choose any class you'd like for this controller to respect. 96 | - --ingress-class=alb 97 | 98 | # REQUIRED 99 | # Name of your cluster. Used when naming resources created 100 | # by the ALB Ingress Controller, providing distinction between 101 | # clusters. 102 | - --cluster-name=__REPLACE_K8S_CLUSTER_NAME__ 103 | 104 | # AWS VPC ID this ingress controller will use to create AWS resources. 105 | # If unspecified, it will be discovered from ec2metadata. 106 | - --aws-vpc-id=__REPLACE_VPC_ID__ 107 | 108 | # AWS region this ingress controller will operate in. 109 | # If unspecified, it will be discovered from ec2metadata. 110 | # List of regions: http://docs.aws.amazon.com/general/latest/gr/rande.html#vpc_region 111 | - --aws-region=__REPLACE_AWS_REGION__ 112 | 113 | # Enables logging on all outbound requests sent to the AWS API. 114 | # If logging is desired, set to true. 115 | # - ---aws-api-debug 116 | # Maximum number of times to retry the aws calls. 117 | # defaults to 10. 118 | # - --aws-max-retries=10 119 | #env: 120 | # AWS key id for authenticating with the AWS API. 121 | # This is only here for examples. It's recommended you instead use 122 | # a project like kube2iam for granting access. 123 | # - name: AWS_REGION 124 | # value: __REPLACE_AWS_REGION__ 125 | 126 | # AWS key secret for authenticating with the AWS API. 127 | # This is only here for examples. It's recommended you instead use 128 | # a project like kube2iam for granting access. 129 | #- name: AWS_SECRET_ACCESS_KEY 130 | # value: SECRETVALUE 131 | # Repository location of the ALB Ingress Controller. 132 | image: docker.io/amazon/aws-alb-ingress-controller:v1.1.2 133 | imagePullPolicy: Always 134 | serviceAccountName: alb-ingress-controller 135 | --- 136 | 137 | -------------------------------------------------------------------------------- /bootstrap/apache2-dashboard-init-with-http-redirect.conf: -------------------------------------------------------------------------------- 1 | 2 | ServerAdmin webmaster@localhost 3 | DocumentRoot /var/www 4 | 5 | RewriteEngine On 6 | RewriteCond %{HTTPS} off 7 | RewriteRule (.*) https://%{SERVER_NAME}/$1 [R,L] 8 | 9 | 10 | 11 | 12 | ServerAdmin webmaster@localhost 13 | DocumentRoot /var/www 14 | ProxyRequests Off 15 | ProxyPreserveHost Off 16 | 17 | AllowEncodedSlashes NoDecode 18 | 19 | 20 | AuthType Basic 21 | AuthName "Kubernetes Dashboard" 22 | AuthBasicProvider file 23 | AuthUserFile "/opt/htpasswd-dashboard" 24 | Require valid-user 25 | 26 | 27 | RequestHeader unset Authorization 28 | 29 | Redirect "/ui" /api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/overview?namespace=_all 30 | 31 | ProxyPass /ui ! 32 | ProxyPass / http://127.0.0.1:8001/ nocanon 33 | ProxyPassReverse / http://127.0.0.1:8001/ 34 | 35 | CustomLog ${APACHE_LOG_DIR}/access.log combined 36 | 37 | -------------------------------------------------------------------------------- /bootstrap/banner_message.txt: -------------------------------------------------------------------------------- 1 | ####################################################### 2 | # _ __ _ _ # 3 | # | |/ / | | | | # 4 | # | ' /_ _| |__ ___ _ __ _ __ ___| |_ ___ ___ # 5 | # | <| | | | '_ \ / _ \ '__| '_ \ / _ \ __/ _ \/ __| # 6 | # | . \ |_| | |_) | __/ | | | | | __/ || __/\__ \ # 7 | # |_|\_\__,_|_.__/ \___|_| |_| |_|\___|\__\___||___/ # 8 | # | _ \ | | (_) # 9 | # | |_) | __ _ ___| |_ _ ___ _ __ # 10 | # | _ < / _` / __| __| |/ _ \| '_ \ # 11 | # | |_) | (_| \__ \ |_| | (_) | | | | # 12 | # |____/ \__,_|___/\__|_|\___/|_| |_| # 13 | ####################################################### 14 | -------------------------------------------------------------------------------- /bootstrap/bastion-bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # Kubernetes Bastion Bootstrapping 3 | 4 | # Configuration 5 | PROGRAM='Kubernetes Bastion' 6 | 7 | ##################################### Functions Definitions 8 | function checkos () { 9 | echo "${FUNCNAME[0]} Started ..." 10 | platform='unknown' 11 | unamestr=`uname` 12 | if [[ "$unamestr" == 'Linux' ]]; then 13 | platform='linux' 14 | else 15 | echo "[WARNING] This script is not supported on MacOS or freebsd" 16 | exit 1 17 | fi 18 | echo "${FUNCNAME[0]} Ended" 19 | } 20 | 21 | function usage () { 22 | echo "$0 " 23 | echo " " 24 | echo "options:" 25 | echo -e "--help \t Show options for this script" 26 | echo -e "--banner \t Enable or Disable Bastion Message" 27 | echo -e "--enable \t SSH Banner" 28 | echo -e "--tcp-forwarding \t Enable or Disable TCP Forwarding" 29 | echo -e "--x11-forwarding \t Enable or Disable X11 Forwarding" 30 | } 31 | 32 | function chkstatus () { 33 | echo "${FUNCNAME[0]} Started ..." 34 | if [ $? -eq 0 ] 35 | then 36 | echo "Script [PASS]" 37 | else 38 | echo "Script [FAILED]" >&2 39 | exit 1 40 | fi 41 | } 42 | 43 | function osrelease () { 44 | echo "${FUNCNAME[0]} Started ..." 45 | OS=`cat /etc/os-release | grep '^NAME=' | tr -d \" | sed 's/\n//g' | sed 's/NAME=//g'` 46 | if [ "$OS" == "Ubuntu" ]; then 47 | echo "Ubuntu" 48 | elif [ "$OS" == "Amazon Linux AMI" ]; then 49 | echo "AMZN" 50 | elif [ "$OS" == "CentOS Linux" ]; then 51 | echo "CentOS" 52 | else 53 | echo "Operating System Not Found" 54 | fi 55 | echo "${FUNCNAME[0]} Ended" >> /var/log/cfn-init.log 56 | } 57 | 58 | 59 | function request_eip() { 60 | echo "${FUNCNAME[0]} Started ..." 61 | release=$(osrelease) 62 | export Region=`curl http://169.254.169.254/latest/meta-data/placement/availability-zone | rev | cut -c 2- | rev` 63 | 64 | #Check if EIP already assigned. 65 | ALLOC=1 66 | ZERO=0 67 | INSTANCE_IP=`ifconfig -a | grep inet | awk {'print $2'} | sed 's/addr://g' | head -1` 68 | ASSIGNED=$(aws ec2 describe-addresses --region $Region --output text | grep $INSTANCE_IP | wc -l) 69 | if [ "$ASSIGNED" -gt "$ZERO" ]; then 70 | echo "Already assigned an EIP." 71 | else 72 | aws ec2 describe-addresses --region $Region --output text > /query.txt 73 | #Ensure we are only using EIPs from our Stack 74 | line=`curl http://169.254.169.254/latest/user-data/ | grep EIP_LIST` 75 | IFS=$':' DIRS=(${line//$','/:}) # Replace tabs with colons. 76 | 77 | for (( i=0 ; i<${#DIRS[@]} ; i++ )); do 78 | EIP=`echo ${DIRS[i]} | sed 's/\"//g' | sed 's/EIP_LIST=//g'` 79 | if [ $EIP != "Null" ]; then 80 | #echo "$i: $EIP" 81 | grep "$EIP" /query.txt >> /query2.txt; 82 | fi 83 | done 84 | mv /query2.txt /query.txt 85 | 86 | 87 | AVAILABLE_EIPs=`cat /query.txt | wc -l` 88 | 89 | if [ "$AVAILABLE_EIPs" -gt "$ZERO" ]; then 90 | FIELD_COUNT="5" 91 | INSTANCE_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) 92 | echo "Running associate_eip_now" 93 | while read name; 94 | do 95 | #EIP_ENTRY=$(echo $name | grep eip | wc -l) 96 | EIP_ENTRY=$(echo $name | grep eni | wc -l) 97 | echo "EIP: $EIP_ENTRY" 98 | if [ "$EIP_ENTRY" -eq 1 ]; then 99 | echo "Already associated with an instance" 100 | echo "" 101 | else 102 | export EIP=`echo "$name" | sed 's/[\s]+/,/g' | awk {'print $4'}` 103 | EIPALLOC=`echo $name | awk {'print $2'}` 104 | echo "NAME: $name" 105 | echo "EIP: $EIP" 106 | echo "EIPALLOC: $EIPALLOC" 107 | aws ec2 associate-address --instance-id $INSTANCE_ID --allocation-id $EIPALLOC --region $Region 108 | fi 109 | done < /query.txt 110 | else 111 | echo "[ERROR] No Elastic IPs available in this region" 112 | exit 1 113 | fi 114 | 115 | INSTANCE_IP=`ifconfig -a | grep inet | awk {'print $2'} | sed 's/addr://g' | head -1` 116 | ASSIGNED=$(aws ec2 describe-addresses --region $Region --output text | grep $INSTANCE_IP | wc -l) 117 | if [ "$ASSIGNED" -eq 1 ]; then 118 | echo "EIP successfully assigned." 119 | else 120 | #Retry 121 | while [ "$ASSIGNED" -eq "$ZERO" ] 122 | do 123 | sleep 3 124 | request_eip 125 | INSTANCE_IP=`ifconfig -a | grep inet | awk {'print $2'} | sed 's/addr://g' | head -1` 126 | ASSIGNED=$(aws ec2 describe-addresses --region $Region --output text | grep $INSTANCE_IP | wc -l) 127 | done 128 | fi 129 | fi 130 | 131 | echo "${FUNCNAME[0]} Ended" 132 | } 133 | 134 | function call_request_eip() { 135 | echo "${FUNCNAME[0]} Started ..." 136 | Region=`curl http://169.254.169.254/latest/meta-data/placement/availability-zone | rev | cut -c 2- | rev` 137 | ZERO=0 138 | INSTANCE_IP=`ifconfig -a | grep inet | awk {'print $2'} | sed 's/addr://g' | head -1` 139 | ASSIGNED=$(aws ec2 describe-addresses --region $Region --output text | grep $INSTANCE_IP | wc -l) 140 | if [ "$ASSIGNED" -gt "$ZERO" ]; then 141 | echo "Already assigned an EIP." 142 | else 143 | WAIT=$(shuf -i 1-30 -n 1) 144 | echo "Waiting for $WAIT ..." 145 | sleep "$WAIT" 146 | request_eip 147 | fi 148 | echo "${FUNCNAME[0]} Ended" 149 | } 150 | 151 | function prevent_process_snooping() { 152 | echo "${FUNCNAME[0]} Started ..." 153 | # Prevent bastion host users from viewing processes owned by other users. 154 | mount -o remount,rw,hidepid=2 /proc 155 | awk '!/proc/' /etc/fstab > temp && mv temp /etc/fstab 156 | echo "proc /proc proc defaults,hidepid=2 0 0" >> /etc/fstab 157 | echo "${FUNCNAME[0]} Ended" 158 | } 159 | 160 | ##################################### End Function Definitions 161 | 162 | # Call checkos to ensure platform is Linux 163 | checkos 164 | 165 | ## set an initial value 166 | SSH_BANNER="LINUX BASTION" 167 | 168 | # Read the options from cli input 169 | TEMP=`getopt -o h: --long help,banner:,enable:,tcp-forwarding:,x11-forwarding: -n $0 -- "$@"` 170 | eval set -- "$TEMP" 171 | 172 | 173 | if [ $# == 1 ] ; then echo "No input provided! type ($0 --help) to see usage help" >&2 ; exit 1 ; fi 174 | 175 | # extract options and their arguments into variables. 176 | while true; do 177 | case "$1" in 178 | -h | --help) 179 | usage 180 | exit 1 181 | ;; 182 | --banner) 183 | BANNER_PATH="$2"; 184 | shift 2 185 | ;; 186 | --enable) 187 | ENABLE="$2"; 188 | shift 2 189 | ;; 190 | --tcp-forwarding) 191 | TCP_FORWARDING="$2"; 192 | shift 2 193 | ;; 194 | --x11-forwarding) 195 | X11_FORWARDING="$2"; 196 | shift 2 197 | ;; 198 | --) 199 | break 200 | ;; 201 | *) 202 | break 203 | ;; 204 | esac 205 | done 206 | 207 | # BANNER CONFIGURATION 208 | BANNER_FILE="/etc/ssh_banner" 209 | if [[ $ENABLE == "true" ]];then 210 | if [ -z ${BANNER_PATH} ];then 211 | echo "BANNER_PATH is null skipping ..." 212 | else 213 | echo "BANNER_PATH = ${BANNER_PATH}" 214 | echo "Creating Banner in ${BANNER_FILE}" 215 | if [ $BANNER_FILE ] ;then 216 | echo "[INFO] Installing banner ... " 217 | echo -e "\n Banner ${BANNER_FILE}" >>/etc/ssh/sshd_config 218 | else 219 | echo "[INFO] banner file is not accessible skipping ..." 220 | exit 1; 221 | fi 222 | fi 223 | else 224 | echo "Banner message is not enabled!" 225 | fi 226 | 227 | release=$(osrelease) 228 | 229 | prevent_process_snooping 230 | 231 | call_request_eip 232 | 233 | systemctl restart ssh sshd 234 | 235 | echo "Bootstrap complete." 236 | 237 | exit 0 238 | -------------------------------------------------------------------------------- /bootstrap/cluster-autoscaler.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | labels: 6 | k8s-addon: cluster-autoscaler.addons.k8s.io 7 | k8s-app: cluster-autoscaler 8 | name: cluster-autoscaler 9 | namespace: kube-system 10 | --- 11 | apiVersion: rbac.authorization.k8s.io/v1beta1 12 | kind: ClusterRole 13 | metadata: 14 | name: cluster-autoscaler 15 | labels: 16 | k8s-addon: cluster-autoscaler.addons.k8s.io 17 | k8s-app: cluster-autoscaler 18 | rules: 19 | - apiGroups: [""] 20 | resources: ["events","endpoints"] 21 | verbs: ["create", "patch"] 22 | - apiGroups: [""] 23 | resources: ["pods/eviction"] 24 | verbs: ["create"] 25 | - apiGroups: [""] 26 | resources: ["pods/status"] 27 | verbs: ["update"] 28 | - apiGroups: [""] 29 | resources: ["endpoints"] 30 | resourceNames: ["cluster-autoscaler"] 31 | verbs: ["get","update"] 32 | - apiGroups: [""] 33 | resources: ["nodes"] 34 | verbs: ["watch","list","get","update"] 35 | - apiGroups: [""] 36 | resources: ["pods","services","replicationcontrollers","persistentvolumeclaims","persistentvolumes"] 37 | verbs: ["watch","list","get"] 38 | - apiGroups: ["extensions"] 39 | resources: ["replicasets","daemonsets"] 40 | verbs: ["watch","list","get"] 41 | - apiGroups: ["policy"] 42 | resources: ["poddisruptionbudgets"] 43 | verbs: ["watch","list"] 44 | - apiGroups: ["apps"] 45 | resources: ["statefulsets"] 46 | verbs: ["watch","list","get"] 47 | - apiGroups: ["storage.k8s.io"] 48 | resources: ["storageclasses"] 49 | verbs: ["watch","list","get"] 50 | 51 | --- 52 | apiVersion: rbac.authorization.k8s.io/v1beta1 53 | kind: Role 54 | metadata: 55 | name: cluster-autoscaler 56 | namespace: kube-system 57 | labels: 58 | k8s-addon: cluster-autoscaler.addons.k8s.io 59 | k8s-app: cluster-autoscaler 60 | rules: 61 | - apiGroups: [""] 62 | resources: ["configmaps"] 63 | verbs: ["create"] 64 | - apiGroups: [""] 65 | resources: ["configmaps"] 66 | resourceNames: ["cluster-autoscaler-status"] 67 | verbs: ["delete","get","update"] 68 | 69 | --- 70 | apiVersion: rbac.authorization.k8s.io/v1beta1 71 | kind: ClusterRoleBinding 72 | metadata: 73 | name: cluster-autoscaler 74 | labels: 75 | k8s-addon: cluster-autoscaler.addons.k8s.io 76 | k8s-app: cluster-autoscaler 77 | roleRef: 78 | apiGroup: rbac.authorization.k8s.io 79 | kind: ClusterRole 80 | name: cluster-autoscaler 81 | subjects: 82 | - kind: ServiceAccount 83 | name: cluster-autoscaler 84 | namespace: kube-system 85 | 86 | --- 87 | apiVersion: rbac.authorization.k8s.io/v1beta1 88 | kind: RoleBinding 89 | metadata: 90 | name: cluster-autoscaler 91 | namespace: kube-system 92 | labels: 93 | k8s-addon: cluster-autoscaler.addons.k8s.io 94 | k8s-app: cluster-autoscaler 95 | roleRef: 96 | apiGroup: rbac.authorization.k8s.io 97 | kind: Role 98 | name: cluster-autoscaler 99 | subjects: 100 | - kind: ServiceAccount 101 | name: cluster-autoscaler 102 | namespace: kube-system 103 | 104 | --- 105 | apiVersion: apps/v1 106 | kind: Deployment 107 | metadata: 108 | name: cluster-autoscaler 109 | namespace: kube-system 110 | labels: 111 | app: cluster-autoscaler 112 | spec: 113 | replicas: 1 114 | selector: 115 | matchLabels: 116 | app: cluster-autoscaler 117 | template: 118 | metadata: 119 | labels: 120 | app: cluster-autoscaler 121 | spec: 122 | serviceAccountName: cluster-autoscaler 123 | tolerations: 124 | - effect: NoSchedule 125 | key: node-role.kubernetes.io/master 126 | nodeSelector: 127 | kubernetes.io/role: master 128 | containers: 129 | - image: {{IMAGE}} 130 | name: cluster-autoscaler 131 | resources: 132 | limits: 133 | cpu: 100m 134 | memory: 300Mi 135 | requests: 136 | cpu: 100m 137 | memory: 300Mi 138 | command: 139 | - ./cluster-autoscaler 140 | - --v=4 141 | - --stderrthreshold=info 142 | - --cloud-provider={{CLOUD_PROVIDER}} 143 | - --skip-nodes-with-local-storage=false 144 | - --nodes={{MIN_NODES}}:{{MAX_NODES}}:{{GROUP_NAME}} 145 | env: 146 | - name: AWS_REGION 147 | value: {{AWS_REGION}} 148 | volumeMounts: 149 | - name: ssl-certs 150 | mountPath: {{SSL_CERT_PATH}} 151 | readOnly: true 152 | imagePullPolicy: "Always" 153 | volumes: 154 | - name: ssl-certs 155 | hostPath: 156 | path: "{{SSL_CERT_PATH}}" 157 | -------------------------------------------------------------------------------- /bootstrap/kops-cluster-additionalpolicies.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "Effect": "Allow", 4 | "Action": [ 5 | "acm:*" 6 | ], 7 | "Resource": "*" 8 | }, 9 | { 10 | "Effect": "Allow", 11 | "Action": [ 12 | "autoscaling:*" 13 | ], 14 | "Resource": "*" 15 | }, 16 | { 17 | "Effect": "Allow", 18 | "Action": [ 19 | "ec2:*" 20 | ], 21 | "Resource": "*" 22 | }, 23 | { 24 | "Effect": "Allow", 25 | "Action": [ 26 | "elasticloadbalancing:*" 27 | ], 28 | "Resource": "*" 29 | }, 30 | { 31 | "Effect": "Allow", 32 | "Action": [ 33 | "iam:CreateServiceLinkedRole", 34 | "iam:GetServerCertificate", 35 | "iam:ListServerCertificates" 36 | ], 37 | "Resource": "*" 38 | }, 39 | { 40 | "Effect": "Allow", 41 | "Action": [ 42 | "ecr:*" 43 | ], 44 | "Resource": [ 45 | "*" 46 | ] 47 | }, 48 | { 49 | "Effect": "Allow", 50 | "Action": [ 51 | "logs:*" 52 | ], 53 | "Resource": [ 54 | "*" 55 | ] 56 | }, 57 | { 58 | "Effect": "Allow", 59 | "Action": [ 60 | "route53:ChangeResourceRecordSets" 61 | ], 62 | "Resource": [ 63 | "arn:aws:route53:::hostedzone/*" 64 | ] 65 | }, 66 | { 67 | "Effect": "Allow", 68 | "Action": [ 69 | "route53:ListHostedZones", 70 | "route53:ListResourceRecordSets" 71 | ], 72 | "Resource": [ 73 | "*" 74 | ] 75 | }, 76 | { 77 | "Effect": "Allow", 78 | "Action": [ 79 | "s3:Get*", 80 | "s3:List*" 81 | ], 82 | "Resource": "*" 83 | }, 84 | { 85 | "Effect": "Allow", 86 | "Action": [ 87 | "waf-regional:GetWebACLForResource", 88 | "waf-regional:GetWebACL", 89 | "waf-regional:AssociateWebACL", 90 | "waf-regional:DisassociateWebACL" 91 | ], 92 | "Resource": "*" 93 | }, 94 | { 95 | "Effect": "Allow", 96 | "Action": [ 97 | "waf:GetWebACL", 98 | "waf:AssociateWebACL", 99 | "waf:DisassociateWebACL" 100 | ], 101 | "Resource": "*" 102 | }, 103 | { 104 | "Effect": "Allow", 105 | "Action": [ 106 | "kms:*" 107 | ], 108 | "Resource": "*" 109 | }, 110 | { 111 | "Effect": "Allow", 112 | "Action": [ 113 | "tag:GetResources", 114 | "tag:TagResources", 115 | "tag:AddResourceTags", 116 | "tag:RemoveResourceTags", 117 | "tag:TagResources", 118 | "tag:UntagResources" 119 | ], 120 | "Resource": "*" 121 | }, 122 | { 123 | "Effect": "Allow", 124 | "Action": [ 125 | "sns:Publish" 126 | ], 127 | "Resource": [ 128 | "*" 129 | ] 130 | }, 131 | { 132 | "Effect": "Allow", 133 | "Action": [ 134 | "s3:*" 135 | ], 136 | "Resource": "*" 137 | }, 138 | { 139 | "Effect": "Allow", 140 | "Action": [ 141 | "ssm:*" 142 | ], 143 | "Resource": "*" 144 | }, 145 | { 146 | "Effect": "Allow", 147 | "Action": [ 148 | "ssmmessages:*" 149 | ], 150 | "Resource": "*" 151 | }, 152 | { 153 | "Effect": "Allow", 154 | "Action": [ 155 | "ec2messages:*" 156 | ], 157 | "Resource": "*" 158 | }, 159 | { 160 | "Effect": "Allow", 161 | "Action": [ 162 | "ds:CreateComputer", 163 | "ds:DescribeDirectories" 164 | ], 165 | "Resource": "*" 166 | }, 167 | { 168 | "Effect": "Allow", 169 | "Action": [ 170 | "cloudwatch:PutMetricData" 171 | ], 172 | "Resource": "*" 173 | } 174 | ] 175 | -------------------------------------------------------------------------------- /bootstrap/kops-sharedvpc-iam-yamlconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | 3 | import boto3 4 | import yaml 5 | import sys 6 | import os 7 | import time 8 | 9 | 10 | print "START." 11 | print time.ctime() 12 | 13 | 14 | #defaults 15 | region="eu-west-1" 16 | kopsconf_input="demo.yaml" 17 | kopsconf_additinalpolicies="kops-cluster-additionalpolicies.json" 18 | kopsconf_output_file="out.yaml" 19 | docker_awslogs_group="K8s-Docker" 20 | 21 | #aws region 22 | try: 23 | region=sys.argv[1] 24 | except: 25 | print "define ARG1: region!" 26 | sys.exit(1) 27 | 28 | #generated kops input config 29 | try: 30 | kopsconf_input=sys.argv[2] 31 | except: 32 | print "define ARG2: kops input config!" 33 | sys.exit(1) 34 | 35 | #additional policies 36 | try: 37 | kopsconf_additinalpolicies=sys.argv[3] 38 | except: 39 | print "define ARG3: additional JSON policy files for master/nodes" 40 | sys.exit(1) 41 | 42 | 43 | #output kops config yaml file 44 | try: 45 | kopsconf_output_file=sys.argv[4] 46 | except: 47 | print "define ARG5: kops output config" 48 | sys.exit(1) 49 | 50 | #maxspotprice for nodes 51 | max_spot_price_for_node=0.0 52 | try: 53 | max_spot_price_for_node=sys.argv[5] 54 | except: 55 | print "define ARG6: max spot price, unless 0: on-demand" 56 | pass 57 | 58 | #nodes capacity max 59 | max_nodes_capacity=None 60 | try: 61 | max_nodes_capacity=sys.argv[6] 62 | except: 63 | print "define ARG7: max number of nodes, unless equals min=max" 64 | pass 65 | 66 | if not os.path.exists(kopsconf_input): 67 | print "Missing kiops config input file!" 68 | sys.exit(1) 69 | 70 | if not os.path.exists(kopsconf_additinalpolicies): 71 | print "Missing additonal policy file!" 72 | sys.exit(1) 73 | 74 | yl=None 75 | 76 | #[ {az-name: subnet_id} ... ] 77 | private_subnets={} 78 | public_subnets={} 79 | 80 | #subnet config to replace in kops config 81 | replace_subnets=[] 82 | 83 | with open(kopsconf_input,"r") as f: 84 | yl=yaml.safe_load_all(f.read()) 85 | 86 | kops=list(yl) 87 | vpcid=kops[0].get("spec").get("networkID") 88 | ec2 = boto3.resource('ec2',region_name=region) 89 | ec2client = boto3.client('ec2',region_name=region) 90 | vpc = ec2.Vpc(vpcid) 91 | subnet_iterator = vpc.subnets.all() 92 | 93 | #determine private subnets by routes (NO igw in routes associated with subnet) 94 | for s in subnet_iterator: 95 | public=False 96 | sid=s.subnet_id 97 | az=s.availability_zone 98 | #print sid 99 | #print az 100 | response = ec2client.describe_route_tables( 101 | Filters=[ 102 | { 103 | 'Name': 'association.subnet-id', 104 | 'Values': [ 105 | sid 106 | ] 107 | } 108 | ] 109 | ) 110 | rtb = response['RouteTables'][0]['Associations'][0]['RouteTableId'] 111 | rotb = ec2.RouteTable(rtb) 112 | #print "Routes:" 113 | for r in rotb.routes: 114 | #print r.nat_gateway_id 115 | #print r.gateway_id 116 | if r.gateway_id: 117 | if r.gateway_id.startswith("igw-"): 118 | #print r.gateway_id 119 | #print "skip" 120 | public=True 121 | if public: 122 | public_subnets[az]=sid 123 | continue 124 | private_subnets[az]=sid 125 | 126 | print "Private subnets in VPC: ", vpcid 127 | print private_subnets 128 | print "Public subnets in VPC: ", vpcid 129 | print public_subnets 130 | 131 | 132 | #replace config cidr with id 133 | subnets = kops[0].get("spec").get('subnets') 134 | for subnet in subnets: 135 | if subnet.get('type') == "Utility": 136 | continue 137 | zone=subnet.get('zone') 138 | zname=subnet.get('name') 139 | ztype=subnet.get('type') 140 | newprivatezone={} 141 | if zone in private_subnets: 142 | newprivatezone['id']=private_subnets[zone] 143 | newprivatezone['zone']=zone 144 | newprivatezone['name']=zname 145 | newprivatezone['type']=ztype 146 | if newprivatezone: 147 | replace_subnets.append(newprivatezone) 148 | 149 | for zone,sid in public_subnets.iteritems(): 150 | newpubliczone={} 151 | newpubliczone['id']=sid 152 | newpubliczone['zone']=zone 153 | newpubliczone['name']="utility-"+zone 154 | newpubliczone['type']='Utility' 155 | if newpubliczone: 156 | replace_subnets.append(newpubliczone) 157 | 158 | 159 | print "Set new subnet definitions ..." 160 | print replace_subnets 161 | kops[0]['spec']['subnets']=replace_subnets 162 | 163 | print "Add calico inter-AZ networking ..." 164 | kops[0]['spec']['networking'] = {"calico": {"crossSubnet":True}} 165 | 166 | print "Add swap accept in GENERAL config and enable Custom metric ..." 167 | kops[0]['spec']['kubelet'] = {"failSwapOn":False} 168 | 169 | print "Enable POD autoscaling ..." 170 | kops[0]['spec']['kubeAPIServer'] = {"runtimeConfig": {"autoscaling/v2beta1":"true"}} 171 | 172 | print "Enable Custom Metrics ..." 173 | kops[0]['spec']['kubeControllerManager'] = {"horizontalPodAutoscalerUseRestClients": True} 174 | 175 | # yaml content 176 | ######################### 177 | """ 178 | - content: | 179 | #!/bin/bash -xe 180 | echo "* * * * * root sed -i '0,/^$/ s/^$/exit 0/' /opt/kubernetes/helpers/docker-healthcheck" >> /etc/crontab 181 | name: docker-healthcheck.sh 182 | type: text/x-shellscript 183 | """ 184 | 185 | ########################## 186 | # node configs 187 | ########################## 188 | #print "Add swap accept in MASTER config 189 | kops[1]['spec']['kubelet'] = {"failSwapOn":False} 190 | kops[1]['spec']['additionalUserData'] = [{'content': '#!/bin/bash -xe\ndd if=/dev/zero of=/swapfile count=8192 bs=1MiB\nchmod 600 /swapfile\nmkswap /swapfile\nswapon /swapfile\nsysctl vm.swappiness=10\nsysctl vm.vfs_cache_pressure=50\n', 'type': 'text/x-shellscript', 'name': 'swap.sh'},{'content': '#!/bin/bash -xe\napt-get update\napt-get -y install nfs-common\n', 'type': 'text/x-shellscript', 'name': 'nfs.sh'}] 191 | 192 | 193 | #print "Add swap accept in NODES config 194 | kops[2]['spec']['kubelet'] = {"failSwapOn":False} 195 | kops[2]['spec']['additionalUserData'] = [{'content': '#!/bin/bash -xe\ndd if=/dev/zero of=/swapfile count=8192 bs=1MiB\nmkswap /swapfile\nswapon /swapfile\nsysctl vm.swappiness=10\nsysctl vm.vfs_cache_pressure=50\n', 'type': 'text/x-shellscript', 'name': 'swap.sh'},{'content': '#!/bin/bash -xe\napt-get update\napt-get -y install nfs-common\n', 'type': 'text/x-shellscript', 'name': 'nfs.sh'}] 196 | 197 | kops[2]['spec']['nodeLabels']["beta.kubernetes.io/fluentd-ds-ready"]="true" 198 | ########################## 199 | 200 | 201 | if max_spot_price_for_node: 202 | print "Set MAX SPOT price for NODES: ",str(max_spot_price_for_node) 203 | try: 204 | max_spot_price_for_node=float(max_spot_price_for_node) 205 | if max_spot_price_for_node > 0.0: 206 | kops[2]['spec']['maxPrice']=str(max_spot_price_for_node) 207 | except Exception,e: 208 | print "SPOT ERROR:",str(e) 209 | pass 210 | 211 | #set maximum size for NODES 212 | if max_nodes_capacity: 213 | print "Set MAX ASG size for NODES: ",str(max_nodes_capacity) 214 | kops[2]['spec']['maxSize']=int(max_nodes_capacity) 215 | 216 | print "Apply new policies ..." 217 | if os.path.exists(kopsconf_additinalpolicies): 218 | print "Add policy file: ", kopsconf_additinalpolicies 219 | ap="" 220 | with open(kopsconf_additinalpolicies,"r") as f: 221 | ap=f.read() 222 | additionalpolicies = {'node': ap, 'master': ap} 223 | #print additionalpolicies 224 | kops[0]['spec']['additionalPolicies']=additionalpolicies 225 | 226 | out=yaml.safe_dump_all(kops, default_flow_style=False) 227 | print out 228 | with open(kopsconf_output_file,"w") as f: 229 | f.write(out) 230 | 231 | sys.exit(0) 232 | -------------------------------------------------------------------------------- /bootstrap/kubernetes-dashboard.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # ------------------- Dashboard Secret ------------------- # 16 | 17 | apiVersion: v1 18 | kind: Secret 19 | metadata: 20 | labels: 21 | k8s-app: kubernetes-dashboard 22 | name: kubernetes-dashboard-certs 23 | namespace: kube-system 24 | type: Opaque 25 | 26 | --- 27 | # ------------------- Dashboard Service Account ------------------- # 28 | 29 | apiVersion: v1 30 | kind: ServiceAccount 31 | metadata: 32 | labels: 33 | k8s-app: kubernetes-dashboard 34 | name: kubernetes-dashboard 35 | namespace: kube-system 36 | 37 | --- 38 | # ------------------- Dashboard Role & Role Binding ------------------- # 39 | 40 | kind: Role 41 | apiVersion: rbac.authorization.k8s.io/v1 42 | metadata: 43 | name: kubernetes-dashboard-minimal 44 | namespace: kube-system 45 | rules: 46 | # Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret. 47 | - apiGroups: [""] 48 | resources: ["secrets"] 49 | verbs: ["create"] 50 | # Allow Dashboard to create 'kubernetes-dashboard-settings' config map. 51 | - apiGroups: [""] 52 | resources: ["configmaps"] 53 | verbs: ["create"] 54 | # Allow Dashboard to get, update and delete Dashboard exclusive secrets. 55 | - apiGroups: [""] 56 | resources: ["secrets"] 57 | resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"] 58 | verbs: ["get", "update", "delete"] 59 | # Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map. 60 | - apiGroups: [""] 61 | resources: ["configmaps"] 62 | resourceNames: ["kubernetes-dashboard-settings"] 63 | verbs: ["get", "update"] 64 | # Allow Dashboard to get metrics from heapster. 65 | - apiGroups: [""] 66 | resources: ["services"] 67 | resourceNames: ["heapster"] 68 | verbs: ["proxy"] 69 | - apiGroups: [""] 70 | resources: ["services/proxy"] 71 | resourceNames: ["heapster", "http:heapster:", "https:heapster:"] 72 | verbs: ["get"] 73 | 74 | --- 75 | apiVersion: rbac.authorization.k8s.io/v1 76 | kind: RoleBinding 77 | metadata: 78 | name: kubernetes-dashboard-minimal 79 | namespace: kube-system 80 | roleRef: 81 | apiGroup: rbac.authorization.k8s.io 82 | kind: Role 83 | name: kubernetes-dashboard-minimal 84 | subjects: 85 | - kind: ServiceAccount 86 | name: kubernetes-dashboard 87 | namespace: kube-system 88 | 89 | --- 90 | # ------------------- Dashboard Deployment ------------------- # 91 | 92 | kind: Deployment 93 | apiVersion: apps/v1beta2 94 | metadata: 95 | labels: 96 | k8s-app: kubernetes-dashboard 97 | name: kubernetes-dashboard 98 | namespace: kube-system 99 | spec: 100 | replicas: 1 101 | revisionHistoryLimit: 10 102 | selector: 103 | matchLabels: 104 | k8s-app: kubernetes-dashboard 105 | template: 106 | metadata: 107 | labels: 108 | k8s-app: kubernetes-dashboard 109 | spec: 110 | containers: 111 | - name: kubernetes-dashboard 112 | image: k8s.gcr.io/kubernetes-dashboard-amd64:v1.10.0 113 | ports: 114 | - containerPort: 8443 115 | protocol: TCP 116 | args: 117 | - --auto-generate-certificates 118 | # Uncomment the following line to manually specify Kubernetes API server Host 119 | # If not specified, Dashboard will attempt to auto discover the API server and connect 120 | # to it. Uncomment only if the default does not work. 121 | # - --apiserver-host=http://my-address:port 122 | volumeMounts: 123 | - name: kubernetes-dashboard-certs 124 | mountPath: /certs 125 | # Create on-disk volume to store exec logs 126 | - mountPath: /tmp 127 | name: tmp-volume 128 | livenessProbe: 129 | httpGet: 130 | scheme: HTTPS 131 | path: / 132 | port: 8443 133 | initialDelaySeconds: 30 134 | timeoutSeconds: 30 135 | volumes: 136 | - name: kubernetes-dashboard-certs 137 | secret: 138 | secretName: kubernetes-dashboard-certs 139 | - name: tmp-volume 140 | emptyDir: {} 141 | serviceAccountName: kubernetes-dashboard 142 | # Comment the following tolerations if Dashboard must not be deployed on master 143 | tolerations: 144 | - key: node-role.kubernetes.io/master 145 | effect: NoSchedule 146 | 147 | --- 148 | # ------------------- Dashboard Service ------------------- # 149 | 150 | kind: Service 151 | apiVersion: v1 152 | metadata: 153 | labels: 154 | k8s-app: kubernetes-dashboard 155 | name: kubernetes-dashboard 156 | namespace: kube-system 157 | spec: 158 | ports: 159 | - port: 443 160 | targetPort: 8443 161 | selector: 162 | k8s-app: kubernetes-dashboard 163 | -------------------------------------------------------------------------------- /bootstrap/kubernetes-monitoring.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: ClusterRoleBinding 3 | apiVersion: rbac.authorization.k8s.io/v1beta1 4 | metadata: 5 | name: heapster 6 | roleRef: 7 | apiGroup: rbac.authorization.k8s.io 8 | kind: ClusterRole 9 | name: system:heapster 10 | subjects: 11 | - kind: ServiceAccount 12 | name: heapster 13 | namespace: kube-system 14 | --- 15 | apiVersion: extensions/v1beta1 16 | kind: Deployment 17 | metadata: 18 | name: monitoring-influxdb 19 | namespace: kube-system 20 | spec: 21 | replicas: 1 22 | template: 23 | metadata: 24 | labels: 25 | task: monitoring 26 | k8s-app: influxdb 27 | spec: 28 | containers: 29 | - name: influxdb 30 | image: k8s.gcr.io/heapster-influxdb-amd64:v1.5.2 31 | volumeMounts: 32 | - mountPath: /data 33 | name: influxdb-storage 34 | volumes: 35 | - name: influxdb-storage 36 | emptyDir: {} 37 | --- 38 | apiVersion: v1 39 | kind: Service 40 | metadata: 41 | labels: 42 | task: monitoring 43 | # For use as a Cluster add-on (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons) 44 | # If you are NOT using this as an addon, you should comment out this line. 45 | kubernetes.io/cluster-service: 'true' 46 | kubernetes.io/name: monitoring-influxdb 47 | name: monitoring-influxdb 48 | namespace: kube-system 49 | spec: 50 | ports: 51 | - port: 8086 52 | targetPort: 8086 53 | selector: 54 | k8s-app: influxdb 55 | --- 56 | apiVersion: extensions/v1beta1 57 | kind: Deployment 58 | metadata: 59 | name: monitoring-grafana 60 | namespace: kube-system 61 | spec: 62 | replicas: 1 63 | template: 64 | metadata: 65 | labels: 66 | task: monitoring 67 | k8s-app: grafana 68 | spec: 69 | containers: 70 | - name: grafana 71 | image: k8s.gcr.io/heapster-grafana-amd64:v5.0.4 72 | ports: 73 | - containerPort: 3000 74 | protocol: TCP 75 | volumeMounts: 76 | - mountPath: /etc/ssl/certs 77 | name: ca-certificates 78 | readOnly: true 79 | - mountPath: /var 80 | name: grafana-storage 81 | env: 82 | - name: INFLUXDB_HOST 83 | value: monitoring-influxdb 84 | - name: GF_SERVER_HTTP_PORT 85 | value: "3000" 86 | # The following env variables are required to make Grafana accessible via 87 | # the kubernetes api-server proxy. On production clusters, we recommend 88 | # removing these env variables, setup auth for grafana, and expose the grafana 89 | # service using a LoadBalancer or a public IP. 90 | - name: GF_AUTH_BASIC_ENABLED 91 | value: "false" 92 | - name: GF_AUTH_ANONYMOUS_ENABLED 93 | value: "true" 94 | - name: GF_AUTH_ANONYMOUS_ORG_ROLE 95 | value: Admin 96 | - name: GF_SERVER_ROOT_URL 97 | # If you're only using the API Server proxy, set this value instead: 98 | # value: /api/v1/namespaces/kube-system/services/monitoring-grafana/proxy 99 | value: / 100 | volumes: 101 | - name: ca-certificates 102 | hostPath: 103 | path: /etc/ssl/certs 104 | - name: grafana-storage 105 | emptyDir: {} 106 | --- 107 | apiVersion: v1 108 | kind: Service 109 | metadata: 110 | labels: 111 | # For use as a Cluster add-on (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons) 112 | # If you are NOT using this as an addon, you should comment out this line. 113 | kubernetes.io/cluster-service: 'true' 114 | kubernetes.io/name: monitoring-grafana 115 | name: monitoring-grafana 116 | namespace: kube-system 117 | spec: 118 | # In a production setup, we recommend accessing Grafana through an external Loadbalancer 119 | # or through a public IP. 120 | # type: LoadBalancer 121 | # You could also use NodePort to expose the service at a randomly-generated port 122 | # type: NodePort 123 | ports: 124 | - port: 80 125 | targetPort: 3000 126 | selector: 127 | k8s-app: grafana 128 | --- 129 | apiVersion: v1 130 | kind: ServiceAccount 131 | metadata: 132 | name: heapster 133 | namespace: kube-system 134 | --- 135 | apiVersion: v1 136 | kind: ServiceAccount 137 | metadata: 138 | name: heapster 139 | namespace: kube-system 140 | --- 141 | apiVersion: extensions/v1beta1 142 | kind: Deployment 143 | metadata: 144 | name: heapster 145 | namespace: kube-system 146 | spec: 147 | replicas: 1 148 | template: 149 | metadata: 150 | labels: 151 | task: monitoring 152 | k8s-app: heapster 153 | spec: 154 | serviceAccountName: heapster 155 | containers: 156 | - name: heapster 157 | image: k8s.gcr.io/heapster-amd64:v1.5.4 158 | imagePullPolicy: IfNotPresent 159 | command: 160 | - /heapster 161 | - --source=kubernetes:https://kubernetes.default 162 | - --sink=influxdb:http://monitoring-influxdb.kube-system.svc:8086 163 | --- 164 | apiVersion: v1 165 | kind: Service 166 | metadata: 167 | labels: 168 | task: monitoring 169 | # For use as a Cluster add-on (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons) 170 | # If you are NOT using this as an addon, you should comment out this line. 171 | kubernetes.io/cluster-service: 'true' 172 | kubernetes.io/name: Heapster 173 | name: heapster 174 | namespace: kube-system 175 | spec: 176 | ports: 177 | - port: 80 178 | targetPort: 8082 179 | selector: 180 | k8s-app: heapster 181 | 182 | -------------------------------------------------------------------------------- /bootstrap/purge-s3-versioned-bucket.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | 3 | import boto3 4 | import os 5 | import sys 6 | import time 7 | 8 | bucket=sys.argv[1] 9 | region=sys.argv[2] 10 | 11 | print "DELETE BUCKET: "+bucket 12 | print time.ctime() 13 | 14 | session = boto3.Session(region_name=region) 15 | s3 = session.resource(service_name='s3') 16 | bucket = s3.Bucket(bucket) 17 | bucket.object_versions.delete() 18 | bucket.delete() 19 | 20 | print time.ctime() 21 | print "DONE." 22 | 23 | sys.exit(0) 24 | -------------------------------------------------------------------------------- /bootstrap/tear-down-cluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | AWSRegion=${1} 4 | 5 | echo "TEAR DOWN START..." 6 | 7 | export KOPS_STATE_STORE=`cat /opt/kops-state/KOPS_STATE_STORE` 8 | export KOPS_CLUSTER_NAME=`cat /opt/kops-state/KOPS_CLUSTER_NAME` 9 | export AWS_DEFAULT_REGION=${AWSRegion} 10 | 11 | VPC=`cat /opt/kops-state/KOPS_VPC` 12 | 13 | kops export kubecfg --name $KOPS_CLUSTER_NAME 14 | 15 | echo "Delete k8s ingresses ... " 16 | ingress="" 17 | #delete ingresses 18 | for i in `kubectl get ingress -o yaml | grep "name:" | grep -v hostname | awk '{print $2}'`; 19 | do 20 | echo "Delete ingress: $i..."; 21 | kubectl delete ingress $i --force; 22 | ingress="YES" 23 | sleep 10 24 | 25 | for j in `aws elbv2 describe-target-groups --region ${AWSRegion} --output text | grep arn | grep TARGETGROUPS | awk '{print $10}'`; 26 | do 27 | echo "Target group: $j ..."; 28 | for h in {0..20}; 29 | do 30 | N=`aws elbv2 describe-tags --resource-arns $j --region ${AWSRegion} --output text | grep $i`; 31 | if [[ -n "${N}" ]]; 32 | then 33 | echo "DELETE TARGET GROUP: ${j} ..."; 34 | H=`aws elbv2 delete-target-group --target-group-arn $j --region ${AWSRegion}` 35 | if [[ ! -n $H ]]; 36 | then 37 | echo "Target group deleted."; 38 | break 39 | else 40 | echo "Waiting to delete target group ${H} ..." 41 | sleep 5 42 | continue 43 | fi 44 | else 45 | break; 46 | fi 47 | done 48 | done 49 | done 50 | 51 | #wait for target group deletion, it is async wait to remove ALB target groups 52 | echo "Wait a bit ... " 53 | if [[ "${ingress}" == "YES" ]]; 54 | then 55 | sleep 20 56 | fi 57 | 58 | #delete cluster 59 | echo "Delete cluster ... " 60 | kops delete cluster --name $KOPS_CLUSTER_NAME --yes 61 | 62 | #purge remaining alb SGs 63 | if [[ -n "${VPC}" ]]; 64 | then 65 | echo "Remove ALB SGs from VPC: ${VPC} ..." 66 | for sg in `aws ec2 describe-security-groups --filters Name=vpc-id,Values=${VPC} Name=tag-key,Values=ManagedBy Name=tag-value,Values=alb-ingress --output text --region ${AWSRegion} | grep SECURITYGROUPS | awk '{print $3}'`; 67 | do 68 | echo "Delete SG: $sg "; 69 | aws ec2 delete-security-group --group-id $sg --region ${AWSRegion}; 70 | done 71 | else 72 | echo "NO VPC!" 73 | fi 74 | 75 | #delete local r53 dns zone 76 | echo "Delete R53 ZONE ... " 77 | if [[ -e "/opt/kops-state/KOPS_R53_PRIVATE_HOSTED_ZONE_ID" ]]; 78 | then 79 | R53ZID=`cat /opt/kops-state/KOPS_R53_PRIVATE_HOSTED_ZONE_ID` 80 | if [[ -n ${R53ZID} ]]; 81 | then 82 | aws route53 delete-hosted-zone --id ${R53ZID} --region ${AWSRegion} 83 | else 84 | echo "Missing R53 Zone ID!" 85 | fi 86 | fi 87 | 88 | #delete kops state bucket 89 | echo "Delete kops S3 state bucket ... " 90 | S3BUCKET=`cat /opt/kops-state/KOPS_STATE_STORE | cut -d '/' -f 3` 91 | python purge-s3-versioned-bucket.py ${S3BUCKET} ${AWSRegion} 92 | 93 | #delete log group 94 | echo "Delete AWS logs group ... " 95 | LOG2=`cat /opt/kops-state/KOPS_AWSLOGS` 96 | if [[ -n ${LOG2} ]]; 97 | then 98 | aws logs delete-log-group --log-group-name ${LOG2} --region ${AWSRegion} 99 | fi 100 | 101 | echo "TEAR DOWN DONE. EXIT 0" 102 | exit 0 103 | -------------------------------------------------------------------------------- /cfn-templates/latest-single-natinstance.yaml: -------------------------------------------------------------------------------- 1 | tc2-kuberntes-on-aws-v1.15.yaml -------------------------------------------------------------------------------- /deploy-s3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | aws s3 sync ./ s3://tc2-kubernetes/latest/ --profile=tc2-infra --exclude ".git/*" --exclude "$0" --delete 4 | -------------------------------------------------------------------------------- /docs/TC2_Abstratct_production_grade_Kubernetes_deployment_on_AWS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/totalcloudconsulting/kubernetes-aws/989cb3ec3b397c7d8b6ddb6ba9f9de1289132850/docs/TC2_Abstratct_production_grade_Kubernetes_deployment_on_AWS.pdf -------------------------------------------------------------------------------- /docs/k8s-fullscale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/totalcloudconsulting/kubernetes-aws/989cb3ec3b397c7d8b6ddb6ba9f9de1289132850/docs/k8s-fullscale.png -------------------------------------------------------------------------------- /docs/k8s-small-footprint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/totalcloudconsulting/kubernetes-aws/989cb3ec3b397c7d8b6ddb6ba9f9de1289132850/docs/k8s-small-footprint.png -------------------------------------------------------------------------------- /easy-openvpn/README.md: -------------------------------------------------------------------------------- 1 | # easy-openvpn 2 | 3 | Based on easy-rsa. Added embed-key generation features. Create embed-style VPN certificates, keys, configs easily. 4 | 5 | __Purpose of the project__ 6 | 7 | 1. Deploy OpenVPN setup on Ubuntu/Debian OS in 5 minutes, 3 easy steps. 8 | 2. Easy EMBED-style OpenVPN config generation which contains everything: key, cert, config in __ONE file__ ! 9 | 3. AWS Cloudformation / automation ready (don't ask for anything) 10 | 11 | ---------- 12 | 13 | # Prerequisites 14 | 15 | Ububtu / Debian OS (or based on) server 16 | 17 | __Install openvpn, git, zip__ 18 | 19 | ``` 20 | sudo apt-get install openvpn zip git 21 | ``` 22 | 23 | __Clone__ 24 | 25 | ``` 26 | cd ~ 27 | git clone https://github.com/tatobi/easy-openvpn.git 28 | ``` 29 | 30 | 31 | # Create openvpn/keygen folder 32 | 33 | ``` 34 | sudo mkdir -p /etc/openvpn/keygen 35 | 36 | ``` 37 | 38 | __1. Copy content to the folder__ 39 | 40 | 41 | ``` 42 | sudo cp ~/easy-openvpn/keygen/* /etc/openvpn/keygen/ 43 | ``` 44 | 45 | 46 | __Edit "vars" file__ 47 | 48 | 49 | ``` 50 | sudo nano /etc/openvpn/keygen/vars 51 | ``` 52 | 53 | Scroll dow to the end of file and set up the following variables: 54 | 55 | __!CHANGE SETTINGS HERE!__ 56 | 57 | ``` 58 | ############################################ 59 | # Configure these fields 60 | ############################################ 61 | export OPENVPN_CONF_DIR="/etc/openvpn" 62 | export OPENVPN_LOG_DIR="/var/log/openvpn" 63 | export KEY_SIZE=2048 64 | export CA_EXPIRE=7300 65 | export KEY_EXPIRE=7300 66 | export CRL_EXPIRE=7300 67 | export KEY_COUNTRY="CC" 68 | export KEY_PROVINCE="CHANGE_PROVINCE" 69 | export KEY_CITY="CHANGE_CITY" 70 | export KEY_ORG="CHANGE_ORG" 71 | export KEY_EMAIL="CHANGE_ORG_EMAIL" 72 | export KEY_OU="CHANGE_OU" 73 | export SERVER_ENDPOINT="CHANGE_SERVER_IP" 74 | export SERVER_PORT_TCP="443" 75 | export SERVER_PORT_UDP="1194" 76 | 77 | ``` 78 | 79 | __2. Setup the server at TCP 443 (SSL) port__ 80 | 81 | 82 | ``` 83 | sudo su - 84 | cd /etc/openvpn/keygen 85 | ./create-server-tcp-gw 86 | 87 | START SERVER: 88 | service openvpn@server-tcp-gw start 89 | ``` 90 | 91 | __3. Create embed style OpenVPN config/cert for client__ 92 | 93 | ``` 94 | sudo su - 95 | cd /etc/openvpn/keygen 96 | ./build-key-embed-commongw {cert.name.01} 97 | 98 | ``` 99 | 100 | Download ZIPPED key to client, unzip to openvpn config folder and __thats all__! 101 | After proper setup at client, ALL traffic is going through your server securely. 102 | 103 | ---------- 104 | 105 | # Revoke client cert 106 | ``` 107 | sudo su - 108 | cd /etc/openvpn/keygen 109 | ./revoke-client {cert.name.01} 110 | ``` 111 | 112 | 113 | # Using with PKCS12 114 | 115 | You can create PKCS12 (NOT embedded) certificates: 116 | 117 | ``` 118 | sudo su - 119 | cd /etc/openvpn/keygen 120 | ./build-key-pkcs12-commongw {cert.name.01} 121 | ``` 122 | 123 | ---------- 124 | 125 | # Using UDP / gatewayless (site-to-site) 126 | 127 | Using through UDP means less overhead but maybe blocked by ISPs. It is better for S2S VPN. 128 | 129 | __Additonal routing setup is required!__ 130 | 131 | Please read openvpn documentation how to edit ccd files and server routing. 132 | 133 | # Server 134 | 135 | ``` 136 | sudo su - 137 | cd /etc/openvpn/keygen 138 | ./create-server 139 | 140 | (or already exist by previous setup): 141 | ./build-key-server 142 | ``` 143 | 144 | # Keys 145 | 146 | ``` 147 | sudo su - 148 | cd /etc/openvpn/keygen 149 | 150 | 151 | PKCS12: 152 | ./build-key-pkcs12 {cert.name.02} 153 | 154 | EMBED: 155 | 156 | ./build-key-embed {cert.name.02} 157 | 158 | NORMAL: 159 | ./build-key {cert.name.02} 160 | 161 | ``` 162 | 163 | ---------- 164 | # Purge 165 | 166 | # !!! WARNING clean-all deletes everything !!! 167 | 168 | ``` 169 | sudo su - 170 | cd /etc/openvpn/keygen 171 | ./clean-all 172 | ``` 173 | 174 | ---------- 175 | 176 | Thank you for: easy-rsa project and jinnjo vgithub for pem-split. 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-ca: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Build a root certificate 5 | # 6 | 7 | source ./vars 8 | 9 | if [[ -e $KEY_DIR/ca.crt ]]; 10 | then 11 | echo "WARNING: CA cert already exists! Exit." 12 | exit 1 13 | fi 14 | 15 | 16 | export EASY_RSA="${EASY_RSA:-.}" 17 | "$EASY_RSA/pkitool" --initca $* 18 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-crl-revoke: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ./vars 4 | 5 | CRL="crl.pem" 6 | RT="revoke-test.pem" 7 | 8 | if [ "$KEY_DIR" ]; then 9 | echo "Create revoke CRL ..." 10 | cd "$KEY_DIR" 11 | rm -f "$RT" 12 | chmod og+X $KEY_DIR 13 | 14 | # set defaults 15 | export KEY_CN="" 16 | export KEY_OU="" 17 | 18 | # generate a new CRL -- try to be compatible with 19 | # intermediate PKIs 20 | $OPENSSL ca -gencrl -out "$CRL" -config "$KEY_CONFIG" 21 | 22 | #openssl ca -gencrl -keyfile keys/ca.key -cert keys/ca.crt -out keys/crl.pem -config ./openssl.cnf 23 | 24 | if [ -e export-ca.crt ]; then 25 | cat export-ca.crt "$CRL" >"$RT" 26 | else 27 | cat ca.crt "$CRL" >"$RT" 28 | fi 29 | echo "DONE" 30 | else 31 | echo 'Please source the vars script first (i.e. "source ./vars")' 32 | echo 'Make sure you have edited it to reflect your configuration.' 33 | fi 34 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-dh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Build Diffie-Hellman parameters for the server side 4 | # of an SSL/TLS connection. 5 | 6 | source ./vars 7 | 8 | if [[ -e $KEY_DIR/dh2048.pem ]]; 9 | then 10 | echo "WARNING: dh2048.pem already exists! Exit." 11 | exit 1 12 | fi 13 | 14 | 15 | if [ -d $KEY_DIR ] && [ $KEY_SIZE ]; then 16 | $OPENSSL dhparam -out ${KEY_DIR}/dh${KEY_SIZE}.pem ${KEY_SIZE} 17 | else 18 | echo 'Please source the vars script first (i.e. "source ./vars")' 19 | echo 'Make sure you have edited it to reflect your configuration.' 20 | fi 21 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-inter: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Make an intermediate CA certificate/private key pair using a locally generated 4 | # root certificate. 5 | 6 | source ./vars 7 | 8 | if [[ -e $KEY_DIR/ca.crt ]]; 9 | then 10 | echo "WARNING:CA CERT already exists! Exit." 11 | exit 1 12 | fi 13 | 14 | 15 | export EASY_RSA="${EASY_RSA:-.}" 16 | "$EASY_RSA/pkitool" --inter $* 17 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-key: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Similar to build-key, but protect the private key 5 | # with a password and tar.gz keys into user dir 6 | # 7 | 8 | source ./vars 9 | 10 | if test $# -ne 1; then 11 | echo "usage: build-key "; 12 | exit 1 13 | fi 14 | 15 | if test $KEY_DIR; then 16 | cd $KEY_DIR && \ 17 | export EASY_RSA="${EASY_RSA:-.}" 18 | "$EASY_RSA/pkitool" $* 19 | chmod 0600 $1.key && \ 20 | mkdir $1 && \ 21 | mv $1.* $1/ && \ 22 | rm $1/*.csr && \ 23 | cp ca.crt $1/ && \ 24 | cp ta.key $1/$1.ta.key && \ 25 | sed 's/CHANGE_KEY/'$1'/g' $OPENVPN_CONF_DIR/keygen/client-template.ovpn > $1/$1.ovpn && \ 26 | sed -i 's/CHANGE_TA/'$1'/g' $1/$1.ovpn && \ 27 | sed -i 's/CHANGE_SERVER/'$SERVER_ENDPOINT'/g' $1/$1.ovpn && \ 28 | sed -i 's/CHANGE_PORT/'$SERVER_PORT_UDP'/g' $1/$1.ovpn && \ 29 | cp $OPENVPN_CONF_DIR/keygen/ccd $OPENVPN_CONF_DIR/ccd/$1 30 | cd $1 31 | zip -r $1.zip ./* 32 | else 33 | echo "you must define KEY_DIR" 34 | fi 35 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-key-embed: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Similar to build-key, but protect the private key 5 | # with a password and tar.gz keys into user dir 6 | # 7 | 8 | source ./vars 9 | 10 | if test $# -ne 1; then 11 | echo "usage: build-key "; 12 | exit 1 13 | fi 14 | 15 | if test $KEY_DIR; then 16 | cd $KEY_DIR 17 | if [[ -e $1/$1.key && -d $1 ]]; 18 | then 19 | echo "This key already exist. Try other name! Exit." 20 | exit 1 21 | fi 22 | export EASY_RSA="${EASY_RSA:-.}" 23 | "$EASY_RSA/pkitool" $* 24 | chmod 0600 $1.key && \ 25 | mkdir $1 && \ 26 | mv $1.* $1/ && \ 27 | rm $1/*.csr && \ 28 | cp $1/$1.crt c-tmp.crt && \ 29 | $OPENVPN_CONF_DIR/keygen/pem-split c-tmp.crt && \ 30 | $OPENVPN_CONF_DIR/keygen/pem-split ta.key && \ 31 | cp $1/$1.key c-tmp.key && \ 32 | cp ca.crt $1/ && \ 33 | cp ta.key $1/$1.ta.key && \ 34 | sed 's/CHANGE_SERVER/'$SERVER_ENDPOINT'/g' $OPENVPN_CONF_DIR/keygen/client-template-embed.ovpn > $1/$1.ovpn && \ 35 | sed -i 's/CHANGE_PORT/'$SERVER_PORT_UDP'/g' $1/$1.ovpn && \ 36 | perl -i -p0e 's/CHANGE_TA_KEY_BODY\n/`cat ta.key-0.key`/se' $1/$1.ovpn && \ 37 | perl -i -p0e 's/CHANGE_CA_CRT_BODY\n/`cat ca.crt`/se' $1/$1.ovpn && \ 38 | perl -i -p0e 's/CHANGE_CLIENT_CERT_BODY\n/`cat c-tmp.crt-0.crt`/se' $1/$1.ovpn && \ 39 | perl -i -p0e 's/CHANGE_CLIENT_KEY_BODY\n/`cat c-tmp.key`/se' $1/$1.ovpn && \ 40 | rm -f c-tmp.* && \ 41 | cp $OPENVPN_CONF_DIR/keygen/ccd $OPENVPN_CONF_DIR/ccd/$1 42 | cd $1 43 | zip $1.zip ./$1.ovpn 44 | echo "########################" 45 | echo "DONE. DOWNLOAD EMBED KEY+CONF: $OPENVPN_CONF_DIR/keys/$1/$1.zip" 46 | else 47 | echo "you must define KEY_DIR" 48 | fi 49 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-key-embed-commongw: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Similar to build-key, but protect the private key 5 | # with a password and tar.gz keys into user dir 6 | # 7 | 8 | source ./vars 9 | 10 | if test $# -ne 1; then 11 | echo "usage: build-key "; 12 | exit 1 13 | fi 14 | 15 | if test $KEY_DIR; then 16 | cd $KEY_DIR 17 | if [[ -e $1/$1.key && -d $1 ]]; 18 | then 19 | echo "This key already exist. Try other name! Exit." 20 | exit 1 21 | fi 22 | export EASY_RSA="${EASY_RSA:-.}" 23 | "$EASY_RSA/pkitool" $* 24 | chmod 0600 $1.key && \ 25 | mkdir $1 && \ 26 | mv $1.* $1/ && \ 27 | rm $1/*.csr && \ 28 | cp $1/$1.crt c-tmp.crt && \ 29 | $OPENVPN_CONF_DIR/keygen/pem-split c-tmp.crt && \ 30 | $OPENVPN_CONF_DIR/keygen/pem-split ta.key && \ 31 | cp $1/$1.key c-tmp.key && \ 32 | cp ca.crt $1/ && \ 33 | cp ta.key $1/$1.ta.key && \ 34 | sed 's/CHANGE_SERVER/'$SERVER_ENDPOINT'/g' $OPENVPN_CONF_DIR/keygen/client-template-embed-commongw.ovpn > $1/$1.ovpn && \ 35 | sed -i 's/CHANGE_PORT/'$SERVER_PORT_TCP'/g' $1/$1.ovpn && \ 36 | perl -i -p0e 's/CHANGE_TA_KEY_BODY\n/`cat ta.key-0.key`/se' $1/$1.ovpn && \ 37 | perl -i -p0e 's/CHANGE_CA_CRT_BODY\n/`cat ca.crt`/se' $1/$1.ovpn && \ 38 | perl -i -p0e 's/CHANGE_CLIENT_CERT_BODY\n/`cat c-tmp.crt-0.crt`/se' $1/$1.ovpn && \ 39 | perl -i -p0e 's/CHANGE_CLIENT_KEY_BODY\n/`cat c-tmp.key`/se' $1/$1.ovpn && \ 40 | rm -f c-tmp.* && \ 41 | cp $OPENVPN_CONF_DIR/keygen/ccd $OPENVPN_CONF_DIR/ccd/$1 42 | cd $1 43 | zip $1.zip ./$1.ovpn 44 | echo "DONE. DOWNLOAD EMBED KEY+CONF: $OPENVPN_CONF_DIR/keys/$1/$1.zip" 45 | else 46 | echo "you must define KEY_DIR" 47 | fi 48 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-key-pkcs12: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Similar to build-key, but protect the private key 5 | # with a password and tar.gz keys into user dir 6 | # 7 | 8 | source ./vars 9 | 10 | if test $# -ne 1; then 11 | echo "usage: $0 "; 12 | exit 1 13 | fi 14 | 15 | if test $KEY_DIR; then 16 | cd $KEY_DIR 17 | if [[ -e $1/$1.key && -d $1 ]]; 18 | then 19 | echo "This key already exist. Try other name! Exit." 20 | exit 1 21 | fi 22 | export EASY_RSA="${EASY_RSA:-.}" 23 | "$EASY_RSA/pkitool" --pkcs12 $* 24 | chmod 0600 $1.p12 && \ 25 | mkdir $1 && \ 26 | mv $1.* $1/ && \ 27 | rm -f $1/*.csr && \ 28 | cp ta.key $1/$1.ta.key && \ 29 | sed 's/CHANGE_KEY/'$1'/g' $OPENVPN_CONF_DIR/keygen/client-template.p12.ovpn > $1/$1.ovpn && \ 30 | sed -i 's/CHANGE_TA/'$1'/g' $1/$1.ovpn && \ 31 | sed -i 's/CHANGE_SERVER/'$SERVER_ENDPOINT'/g' $1/$1.ovpn && \ 32 | sed -i 's/CHANGE_PORT/'$SERVER_PORT_UDP'/g' $1/$1.ovpn && \ 33 | cp $OPENVPN_CONF_DIR/keygen/ccd $OPENVPN_CONF_DIR/ccd/$1 34 | cd $1 35 | zip -r $1.zip ./*.ovpn ./*ta.key ./*.p12 36 | echo "DONE. KEY AND CONFIG:: $1.zip" 37 | else 38 | echo "you must define KEY_DIR..." 39 | fi 40 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-key-pkcs12-commongw: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Similar to build-key, but protect the private key 5 | # with a password and tar.gz keys into user dir 6 | # 7 | 8 | source ./vars 9 | 10 | if test $# -ne 1; then 11 | echo "usage: $0 "; 12 | exit 1 13 | fi 14 | 15 | if test $KEY_DIR; then 16 | cd $KEY_DIR 17 | if [[ -e $1/$1.key && -d $1 ]]; 18 | then 19 | echo "This key already exist. Try other name! Exit." 20 | exit 1 21 | fi 22 | export EASY_RSA="${EASY_RSA:-.}" 23 | "$EASY_RSA/pkitool" --pkcs12 $* 24 | chmod 0600 $1.p12 && \ 25 | mkdir $1 && \ 26 | mv $1.* $1/ && \ 27 | rm -f $1/*.csr && \ 28 | cp ta.key $1/$1.ta.key && \ 29 | sed 's/CHANGE_KEY/'$1'/g' $OPENVPN_CONF_DIR/keygen/client-template.commongw.p12.ovpn > $1/$1.ovpn && \ 30 | sed -i 's/CHANGE_TA/'$1'/g' $1/$1.ovpn && \ 31 | sed -i 's/CHANGE_SERVER/'$SERVER_ENDPOINT'/g' $1/$1.ovpn && \ 32 | sed -i 's/CHANGE_PORT/'$SERVER_PORT_TCP'/g' $1/$1.ovpn && \ 33 | cp $OPENVPN_CONF_DIR/keygen/ccd $OPENVPN_CONF_DIR/ccd/$1 34 | cd $1 35 | zip -r $1.zip ./*.ovpn ./*ta.key ./*.p12 36 | echo "DONE. KEY AND CONFIG:: $1.zip" 37 | else 38 | echo "you must define KEY_DIR..." 39 | fi 40 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-key-server: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Make a certificate/private key pair using a locally generated 4 | # root certificate. 5 | # 6 | # Explicitly set nsCertType to server using the "server" 7 | # extension in the openssl.cnf file. 8 | 9 | source ./vars 10 | 11 | if [[ -e $KEY_DIR/server.key ]]; 12 | then 13 | echo "WARNING:server.key already exists! Exit." 14 | exit 1 15 | fi 16 | 17 | export EASY_RSA="${EASY_RSA:-.}" 18 | "$EASY_RSA/pkitool" --server $* 19 | 20 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-key-server-tcp-commongw: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Make a certificate/private key pair using a locally generated 4 | # root certificate. 5 | # 6 | # Explicitly set nsCertType to server using the "server" 7 | # extension in the openssl.cnf file. 8 | 9 | source ./vars 10 | 11 | if [[ -e $KEY_DIR/server.key ]]; 12 | then 13 | echo "WARNING: server key already exist, dont touch it!" 14 | exit 1 15 | fi 16 | 17 | export EASY_RSA="${EASY_RSA:-.}" 18 | "$EASY_RSA/pkitool" --server $* 19 | 20 | mkdir -p $OPENVPN_LOG_DIR > /dev/null 2>&1 & 21 | chown nobody:root $OPENVPN_LOG_DIR > /dev/null 2>&1 & 22 | 23 | cp server-template-tcp-commongw.conf $OPENVPN_CONF_DIR/server-tcp-gw.conf 24 | sed -i 's/CHANGE_PORT/'$SERVER_PORT_TCP'/g' $OPENVPN_CONF_DIR/server-tcp-gw.conf 25 | cp server-startup-template-tcp-gw.sh $OPENVPN_CONF_DIR/server-tcp-gw-startup.sh 26 | 27 | 28 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-req: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Build a certificate signing request and private key. Use this 4 | # when your root certificate and key is not available locally. 5 | 6 | source ./vars 7 | 8 | if [[ -e $KEY_DIR/server.csr ]]; 9 | then 10 | echo "WARNING:server.csr already exists! Exit." 11 | exit 1 12 | fi 13 | 14 | export EASY_RSA="${EASY_RSA:-.}" 15 | "$EASY_RSA/pkitool" --csr $* 16 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-req-pass: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Like build-req, but protect your private key 4 | # with a password. 5 | 6 | source ./vars 7 | 8 | if [[ -e $KEY_DIR/server.csr ]]; 9 | then 10 | echo "WARNING:server.csr already exists! Exit." 11 | exit 1 12 | fi 13 | 14 | export EASY_RSA="${EASY_RSA:-.}" 15 | "$EASY_RSA/pkitool" --csr --pass $* 16 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/build-ta: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Build Diffie-Hellman parameters for the server side 4 | # of an SSL/TLS connection. 5 | 6 | source ./vars 7 | 8 | if [[ -e $KEY_DIR/ta.key ]]; 9 | then 10 | echo "WARNING:ta.key already exists! Exit." 11 | exit 1 12 | fi 13 | 14 | openvpn --genkey -b 2048 --secret ${KEY_DIR}/ta.key 15 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/ccd: -------------------------------------------------------------------------------- 1 | iroute 10.8.2.0 255.255.255.0 2 | 3 | 4 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/ccd-tcp: -------------------------------------------------------------------------------- 1 | iroute 10.8.3.0 255.255.255.0 2 | 3 | 4 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/clean-all: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Initialize the $KEY_DIR directory. 4 | # Note that this script does a 5 | # rm -rf on $KEY_DIR so be careful! 6 | 7 | echo "" 8 | echo "##################################" 9 | echo "WARNING! You are goung to purge EVERYTHING from OpenVPN!" 10 | echo "##################################" 11 | echo "" 12 | read -p "ARE YOU SURE? [y/n]" -n 1 -r 13 | echo # (optional) move to a new line 14 | if [[ ! $REPLY =~ ^[Yy]$ ]] 15 | then 16 | [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell 17 | fi 18 | 19 | source ./vars 20 | 21 | if [ "$KEY_DIR" ]; then 22 | rm -rf "$KEY_DIR" 23 | mkdir "$KEY_DIR" && \ 24 | chmod go-rwx "$KEY_DIR" && \ 25 | touch "$KEY_DIR/index.txt" && \ 26 | echo 01 >"$KEY_DIR/serial" 27 | rm -rf $OPENVPN_CONF_DIR/ccd/* 28 | rm -f $OPENVPN_CONF_DIR/ipp.txt 29 | rm -f $OPENVPN_CONF_DIR/*.sh 30 | rm -f $OPENVPN_CONF_DIR/*.conf 31 | rm -f $OPENVPN_LOG_DIR/* 32 | echo "" 33 | echo "DONE." 34 | else 35 | echo 'Please source the vars script first (i.e. "source ./vars")' 36 | echo 'Make sure you have edited it to reflect your configuration.' 37 | fi 38 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/client-template-embed-commongw.ovpn: -------------------------------------------------------------------------------- 1 | client 2 | proto tcp-client 3 | dev tun 4 | remote-cert-tls server 5 | remote CHANGE_SERVER CHANGE_PORT 6 | cipher AES-256-CBC 7 | verb 3 8 | mute 20 9 | keepalive 10 120 10 | persist-key 11 | persist-tun 12 | float 13 | resolv-retry infinite 14 | nobind 15 | route-delay 10 30 16 | reneg-sec 86400 17 | tun-mtu 1300 18 | mssfix 1300 19 | pull 20 | key-direction 1 21 | tun-mtu 1300 22 | mssfix 1300 23 | 24 | CHANGE_TA_KEY_BODY 25 | 26 | 27 | CHANGE_CA_CRT_BODY 28 | 29 | 30 | CHANGE_CLIENT_CERT_BODY 31 | 32 | 33 | CHANGE_CLIENT_KEY_BODY 34 | 35 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/client-template-embed.ovpn: -------------------------------------------------------------------------------- 1 | client 2 | proto udp 3 | dev tun 4 | remote-cert-tls server 5 | remote CHANGE_SERVER CHANGE_PORT 6 | cipher AES-256-CBC 7 | verb 3 8 | mute 20 9 | keepalive 10 120 10 | persist-key 11 | persist-tun 12 | float 13 | resolv-retry infinite 14 | nobind 15 | route-delay 10 30 16 | reneg-sec 86400 17 | tun-mtu 1300 18 | mssfix 1300 19 | pull 20 | key-direction 1 21 | tun-mtu 1300 22 | mssfix 1300 23 | 24 | CHANGE_TA_KEY_BODY 25 | 26 | 27 | CHANGE_CA_CRT_BODY 28 | 29 | 30 | CHANGE_CLIENT_CERT_BODY 31 | 32 | 33 | CHANGE_CLIENT_KEY_BODY 34 | 35 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/client-template.commongw.p12.ovpn: -------------------------------------------------------------------------------- 1 | client 2 | proto tcp-client 3 | dev tun 4 | remote-cert-tls server 5 | pkcs12 CHANGE_KEY.p12 6 | tls-auth CHANGE_TA.ta.key 1 7 | remote CHANGE_SERVER CHANGE_PORT 8 | cipher AES-256-CBC 9 | verb 3 10 | mute 20 11 | keepalive 10 120 12 | persist-key 13 | persist-tun 14 | float 15 | resolv-retry infinite 16 | nobind 17 | route-delay 10 30 18 | reneg-sec 86400 19 | pull 20 | tun-mtu 1300 21 | mssfix 1300 22 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/client-template.ovpn: -------------------------------------------------------------------------------- 1 | client 2 | proto udp 3 | dev tun 4 | ca ca.crt 5 | remote-cert-tls server 6 | cert CHANGE_KEY.crt 7 | key CHANGE_KEY.key 8 | remote CHANGE_SERVER CHANGE_PORT 9 | tls-auth CHANGE_TA.ta.key 1 10 | cipher AES-256-CBC 11 | verb 3 12 | mute 20 13 | keepalive 10 120 14 | persist-key 15 | persist-tun 16 | float 17 | resolv-retry infinite 18 | nobind 19 | route-delay 10 30 20 | reneg-sec 86400 21 | pull 22 | tun-mtu 1300 23 | mssfix 1300 24 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/client-template.p12.ovpn: -------------------------------------------------------------------------------- 1 | client 2 | proto udp 3 | dev tun 4 | remote-cert-tls server 5 | pkcs12 CHANGE_KEY.p12 6 | tls-auth CHANGE_TA.ta.key 1 7 | remote CHANGE_SERVER CHANGE_PORT 8 | cipher AES-256-CBC 9 | verb 3 10 | mute 20 11 | keepalive 10 120 12 | persist-key 13 | persist-tun 14 | float 15 | resolv-retry infinite 16 | nobind 17 | route-delay 10 30 18 | reneg-sec 86400 19 | pull 20 | tun-mtu 1300 21 | mssfix 1300 22 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/create-server: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ./vars 4 | 5 | if [[ -e $KEY_DIR/server.key ]]; 6 | then 7 | echo "WARNING: server key already exists! Exit." 8 | exit 1 9 | fi 10 | 11 | mkdir -p $KEY_DIR 12 | chmod og+X $KEY_DIR 13 | 14 | mkdir -p $OPENVPN_CONF_DIR/ccd 15 | chmod og+X $OPENVPN_CONF_DIR/ccd 16 | 17 | mkdir "$KEY_DIR" 18 | chmod go-rwx "$KEY_DIR" 19 | chmod og+rX "$KEY_DIR" 20 | touch "$KEY_DIR/index.txt" 21 | echo 01 >"$KEY_DIR/serial" 22 | 23 | 24 | ./build-ca 25 | ./build-key-server server 26 | ./build-dh 27 | ./build-ta 28 | ./build-crl-revoke 29 | 30 | mkdir -p $OPENVPN_LOG_DIR 31 | chown nobody:root $OPENVPN_LOG_DIR 32 | chmod -R og+rwX $OPENVPN_LOG_DIR 33 | 34 | cp server-template.conf $OPENVPN_CONF_DIR/server.conf 35 | sed -i 's/CHANGE_PORT/'$SERVER_PORT_UDP'/g' $OPENVPN_CONF_DIR/server.conf 36 | cp server-startup-template.sh $OPENVPN_CONF_DIR/server-startup.sh 37 | 38 | 39 | echo "###########################" 40 | echo "DONE, START:" 41 | echo "service openvpn@server start" 42 | echo "###########################" 43 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/create-server-tcp-gw: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ./vars 4 | 5 | if [[ -e $KEY_DIR/server.key ]]; 6 | then 7 | echo "WARNING: server key already exists. Exit." 8 | exit 1 9 | fi 10 | 11 | mkdir -p $KEY_DIR 12 | chmod og+X $KEY_DIR 13 | 14 | mkdir -p $OPENVPN_CONF_DIR/ccd 15 | chmod og+X $OPENVPN_CONF_DIR/ccd 16 | 17 | mkdir "$KEY_DIR" 18 | chmod go-rwx "$KEY_DIR" 19 | chmod og+rX "$KEY_DIR" 20 | touch "$KEY_DIR/index.txt" && \ 21 | echo 01 >"$KEY_DIR/serial" 22 | 23 | 24 | ./build-ca 25 | ./build-key-server-tcp-commongw server 26 | ./build-dh 27 | ./build-ta 28 | ./build-crl-revoke 29 | 30 | mkdir -p $OPENVPN_LOG_DIR 31 | chown nobody:root $OPENVPN_LOG_DIR 32 | chmod -R og+rwX $OPENVPN_LOG_DIR 33 | 34 | cp server-template-tcp-commongw.conf $OPENVPN_CONF_DIR/server-tcp-gw.conf 35 | sed -i 's/CHANGE_PORT/'$SERVER_PORT_TCP'/g' $OPENVPN_CONF_DIR/server-tcp-gw.conf 36 | cp server-startup-template-tcp-gw.sh $OPENVPN_CONF_DIR/server-tcp-gw-startup.sh 37 | 38 | 39 | echo "###########################" 40 | echo "DONE, START:" 41 | echo "service openvpn@server-tcp-gw start" 42 | echo "###########################" 43 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/inherit-inter: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Build a new PKI which is rooted on an intermediate certificate generated 4 | # by ./build-inter or ./pkitool --inter from a parent PKI. The new PKI should 5 | # have independent vars settings, and must use a different KEY_DIR directory 6 | # from the parent. This tool can be used to generate arbitrary depth 7 | # certificate chains. 8 | # 9 | # To build an intermediate CA, follow the same steps for a regular PKI but 10 | # replace ./build-key or ./pkitool --initca with this script. 11 | 12 | # The EXPORT_CA file will contain the CA certificate chain and should be 13 | # referenced by the OpenVPN "ca" directive in config files. The ca.crt file 14 | # will only contain the local intermediate CA -- it's needed by the easy-rsa 15 | # scripts but not by OpenVPN directly. 16 | 17 | source ./vars 18 | 19 | EXPORT_CA="export-ca.crt" 20 | 21 | if [ $# -ne 2 ]; then 22 | echo "usage: $0 " 23 | echo "parent-key-dir: the KEY_DIR directory of the parent PKI" 24 | echo "common-name: the common name of the intermediate certificate in the parent PKI" 25 | exit 1; 26 | fi 27 | 28 | if [ "$KEY_DIR" ]; then 29 | cp "$1/$2.crt" "$KEY_DIR/ca.crt" 30 | cp "$1/$2.key" "$KEY_DIR/ca.key" 31 | 32 | if [ -e "$1/$EXPORT_CA" ]; then 33 | PARENT_CA="$1/$EXPORT_CA" 34 | else 35 | PARENT_CA="$1/ca.crt" 36 | fi 37 | cp "$PARENT_CA" "$KEY_DIR/$EXPORT_CA" 38 | cat "$KEY_DIR/ca.crt" >> "$KEY_DIR/$EXPORT_CA" 39 | else 40 | echo 'Please source the vars script first (i.e. "source ./vars")' 41 | echo 'Make sure you have edited it to reflect your configuration.' 42 | fi 43 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/list-crl: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # list revoked certificates 4 | 5 | source ./vars 6 | 7 | CRL="${1:-crl.pem}" 8 | 9 | if [ "$KEY_DIR" ]; then 10 | cd "$KEY_DIR" && \ 11 | $OPENSSL crl -text -noout -in "$CRL" 12 | else 13 | echo 'Please source the vars script first (i.e. "source ./vars")' 14 | echo 'Make sure you have edited it to reflect your configuration.' 15 | fi 16 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/openssl-0.9.6.cnf: -------------------------------------------------------------------------------- 1 | # For use with easy-rsa version 2.0 2 | 3 | # 4 | # OpenSSL example configuration file. 5 | # This is mostly being used for generation of certificate requests. 6 | # 7 | 8 | # This definition stops the following lines choking if HOME isn't 9 | # defined. 10 | HOME = . 11 | RANDFILE = $ENV::HOME/.rnd 12 | 13 | # Extra OBJECT IDENTIFIER info: 14 | #oid_file = $ENV::HOME/.oid 15 | oid_section = new_oids 16 | 17 | # To use this configuration file with the "-extfile" option of the 18 | # "openssl x509" utility, name here the section containing the 19 | # X.509v3 extensions to use: 20 | # extensions = 21 | # (Alternatively, use a configuration file that has only 22 | # X.509v3 extensions in its main [= default] section.) 23 | 24 | [ new_oids ] 25 | 26 | # We can add new OIDs in here for use by 'ca' and 'req'. 27 | # Add a simple OID like this: 28 | # testoid1=1.2.3.4 29 | # Or use config file substitution like this: 30 | # testoid2=${testoid1}.5.6 31 | 32 | #################################################################### 33 | [ ca ] 34 | default_ca = CA_default # The default ca section 35 | 36 | #################################################################### 37 | [ CA_default ] 38 | 39 | dir = $ENV::KEY_DIR # Where everything is kept 40 | certs = $dir # Where the issued certs are kept 41 | crl_dir = $dir # Where the issued crl are kept 42 | database = $dir/index.txt # database index file. 43 | new_certs_dir = $dir # default place for new certs. 44 | 45 | certificate = $dir/ca.crt # The CA certificate 46 | serial = $dir/serial # The current serial number 47 | crl = $dir/crl.pem # The current CRL 48 | private_key = $dir/ca.key # The private key 49 | RANDFILE = $dir/.rand # private random number file 50 | 51 | x509_extensions = usr_cert # The extentions to add to the cert 52 | 53 | # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs 54 | # so this is commented out by default to leave a V1 CRL. 55 | # crl_extensions = crl_ext 56 | 57 | default_days = $ENV::CA_EXPIRE # how long to certify for 58 | default_crl_days= $ENV::CRL_EXPIRE # how long before next CRL 59 | default_md = sha256 # which md to use. 60 | preserve = no # keep passed DN ordering 61 | 62 | # A few difference way of specifying how similar the request should look 63 | # For type CA, the listed attributes must be the same, and the optional 64 | # and supplied fields are just that :-) 65 | policy = policy_anything 66 | 67 | # For the CA policy 68 | [ policy_match ] 69 | countryName = match 70 | stateOrProvinceName = match 71 | organizationName = match 72 | organizationalUnitName = optional 73 | commonName = supplied 74 | emailAddress = optional 75 | 76 | # For the 'anything' policy 77 | # At this point in time, you must list all acceptable 'object' 78 | # types. 79 | [ policy_anything ] 80 | countryName = optional 81 | stateOrProvinceName = optional 82 | localityName = optional 83 | organizationName = optional 84 | organizationalUnitName = optional 85 | commonName = supplied 86 | emailAddress = optional 87 | 88 | #################################################################### 89 | [ req ] 90 | default_bits = $ENV::KEY_SIZE 91 | default_keyfile = privkey.pem 92 | default_md = sha256 93 | distinguished_name = req_distinguished_name 94 | attributes = req_attributes 95 | x509_extensions = v3_ca # The extentions to add to the self signed cert 96 | 97 | # Passwords for private keys if not present they will be prompted for 98 | # input_password = secret 99 | # output_password = secret 100 | 101 | # This sets a mask for permitted string types. There are several options. 102 | # default: PrintableString, T61String, BMPString. 103 | # pkix : PrintableString, BMPString. 104 | # utf8only: only UTF8Strings. 105 | # nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). 106 | # MASK:XXXX a literal mask value. 107 | # WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings 108 | # so use this option with caution! 109 | string_mask = nombstr 110 | 111 | # req_extensions = v3_req # The extensions to add to a certificate request 112 | 113 | [ req_distinguished_name ] 114 | countryName = Country Name (2 letter code) 115 | countryName_default = $ENV::KEY_COUNTRY 116 | countryName_min = 2 117 | countryName_max = 2 118 | 119 | stateOrProvinceName = State or Province Name (full name) 120 | stateOrProvinceName_default = $ENV::KEY_PROVINCE 121 | 122 | localityName = Locality Name (eg, city) 123 | localityName_default = $ENV::KEY_CITY 124 | 125 | 0.organizationName = Organization Name (eg, company) 126 | 0.organizationName_default = $ENV::KEY_ORG 127 | 128 | # we can do this but it is not needed normally :-) 129 | #1.organizationName = Second Organization Name (eg, company) 130 | #1.organizationName_default = World Wide Web Pty Ltd 131 | 132 | organizationalUnitName = Organizational Unit Name (eg, section) 133 | #organizationalUnitName_default = 134 | 135 | commonName = Common Name (eg, your name or your server\'s hostname) 136 | commonName_max = 64 137 | 138 | emailAddress = Email Address 139 | emailAddress_default = $ENV::KEY_EMAIL 140 | emailAddress_max = 40 141 | 142 | # JY -- added for batch mode 143 | organizationalUnitName_default = $ENV::KEY_OU 144 | commonName_default = $ENV::KEY_CN 145 | 146 | # SET-ex3 = SET extension number 3 147 | 148 | [ req_attributes ] 149 | challengePassword = A challenge password 150 | challengePassword_min = 4 151 | challengePassword_max = 20 152 | 153 | unstructuredName = An optional company name 154 | 155 | [ usr_cert ] 156 | 157 | # These extensions are added when 'ca' signs a request. 158 | 159 | # This goes against PKIX guidelines but some CAs do it and some software 160 | # requires this to avoid interpreting an end user certificate as a CA. 161 | 162 | basicConstraints=CA:FALSE 163 | 164 | # Here are some examples of the usage of nsCertType. If it is omitted 165 | # the certificate can be used for anything *except* object signing. 166 | 167 | # This is OK for an SSL server. 168 | # nsCertType = server 169 | 170 | # For an object signing certificate this would be used. 171 | # nsCertType = objsign 172 | 173 | # For normal client use this is typical 174 | # nsCertType = client, email 175 | 176 | # and for everything including object signing: 177 | # nsCertType = client, email, objsign 178 | 179 | # This is typical in keyUsage for a client certificate. 180 | # keyUsage = nonRepudiation, digitalSignature, keyEncipherment 181 | 182 | # This will be displayed in Netscape's comment listbox. 183 | nsComment = "Easy-RSA Generated Certificate" 184 | 185 | # PKIX recommendations harmless if included in all certificates. 186 | subjectKeyIdentifier=hash 187 | authorityKeyIdentifier=keyid,issuer:always 188 | extendedKeyUsage=clientAuth 189 | keyUsage = digitalSignature 190 | 191 | # This stuff is for subjectAltName and issuerAltname. 192 | # Import the email address. 193 | # subjectAltName=email:copy 194 | subjectAltName=$ENV::KEY_ALTNAMES 195 | 196 | # Copy subject details 197 | # issuerAltName=issuer:copy 198 | 199 | #nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem 200 | #nsBaseUrl 201 | #nsRevocationUrl 202 | #nsRenewalUrl 203 | #nsCaPolicyUrl 204 | #nsSslServerName 205 | 206 | [ server ] 207 | 208 | # JY ADDED -- Make a cert with nsCertType set to "server" 209 | basicConstraints=CA:FALSE 210 | nsCertType = server 211 | nsComment = "Easy-RSA Generated Server Certificate" 212 | subjectKeyIdentifier=hash 213 | authorityKeyIdentifier=keyid,issuer:always 214 | extendedKeyUsage=serverAuth 215 | keyUsage = digitalSignature, keyEncipherment 216 | subjectAltName=$ENV::KEY_ALTNAMES 217 | 218 | [ v3_req ] 219 | 220 | # Extensions to add to a certificate request 221 | 222 | basicConstraints = CA:FALSE 223 | keyUsage = nonRepudiation, digitalSignature, keyEncipherment 224 | 225 | [ v3_ca ] 226 | 227 | 228 | # Extensions for a typical CA 229 | 230 | 231 | # PKIX recommendation. 232 | 233 | subjectKeyIdentifier=hash 234 | 235 | authorityKeyIdentifier=keyid:always,issuer:always 236 | 237 | # This is what PKIX recommends but some broken software chokes on critical 238 | # extensions. 239 | #basicConstraints = critical,CA:true 240 | # So we do this instead. 241 | basicConstraints = CA:true 242 | 243 | # Key usage: this is typical for a CA certificate. However since it will 244 | # prevent it being used as an test self-signed certificate it is best 245 | # left out by default. 246 | # keyUsage = cRLSign, keyCertSign 247 | 248 | # Some might want this also 249 | # nsCertType = sslCA, emailCA 250 | 251 | # Include email address in subject alt name: another PKIX recommendation 252 | # subjectAltName=email:copy 253 | # Copy issuer details 254 | # issuerAltName=issuer:copy 255 | 256 | # DER hex encoding of an extension: beware experts only! 257 | # obj=DER:02:03 258 | # Where 'obj' is a standard or added object 259 | # You can even override a supported extension: 260 | # basicConstraints= critical, DER:30:03:01:01:FF 261 | 262 | [ crl_ext ] 263 | 264 | # CRL extensions. 265 | # Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. 266 | 267 | # issuerAltName=issuer:copy 268 | authorityKeyIdentifier=keyid:always,issuer:always 269 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/openssl-0.9.8.cnf: -------------------------------------------------------------------------------- 1 | # For use with easy-rsa version 2.0 2 | 3 | # 4 | # OpenSSL example configuration file. 5 | # This is mostly being used for generation of certificate requests. 6 | # 7 | 8 | # This definition stops the following lines choking if HOME isn't 9 | # defined. 10 | HOME = . 11 | RANDFILE = $ENV::HOME/.rnd 12 | openssl_conf = openssl_init 13 | 14 | [ openssl_init ] 15 | # Extra OBJECT IDENTIFIER info: 16 | #oid_file = $ENV::HOME/.oid 17 | oid_section = new_oids 18 | engines = engine_section 19 | 20 | # To use this configuration file with the "-extfile" option of the 21 | # "openssl x509" utility, name here the section containing the 22 | # X.509v3 extensions to use: 23 | # extensions = 24 | # (Alternatively, use a configuration file that has only 25 | # X.509v3 extensions in its main [= default] section.) 26 | 27 | [ new_oids ] 28 | 29 | # We can add new OIDs in here for use by 'ca' and 'req'. 30 | # Add a simple OID like this: 31 | # testoid1=1.2.3.4 32 | # Or use config file substitution like this: 33 | # testoid2=${testoid1}.5.6 34 | 35 | #################################################################### 36 | [ ca ] 37 | default_ca = CA_default # The default ca section 38 | 39 | #################################################################### 40 | [ CA_default ] 41 | 42 | dir = $ENV::KEY_DIR # Where everything is kept 43 | certs = $dir # Where the issued certs are kept 44 | crl_dir = $dir # Where the issued crl are kept 45 | database = $dir/index.txt # database index file. 46 | new_certs_dir = $dir # default place for new certs. 47 | 48 | certificate = $dir/ca.crt # The CA certificate 49 | serial = $dir/serial # The current serial number 50 | crl = $dir/crl.pem # The current CRL 51 | private_key = $dir/ca.key # The private key 52 | RANDFILE = $dir/.rand # private random number file 53 | 54 | x509_extensions = usr_cert # The extentions to add to the cert 55 | 56 | # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs 57 | # so this is commented out by default to leave a V1 CRL. 58 | # crl_extensions = crl_ext 59 | 60 | default_days = $ENV::CA_EXPIRE # how long to certify for 61 | default_crl_days= $ENV::CRL_EXPIRE # how long before next CRL 62 | default_md = sha256 # which md to use. 63 | preserve = no # keep passed DN ordering 64 | 65 | # A few difference way of specifying how similar the request should look 66 | # For type CA, the listed attributes must be the same, and the optional 67 | # and supplied fields are just that :-) 68 | policy = policy_anything 69 | 70 | # For the CA policy 71 | [ policy_match ] 72 | countryName = match 73 | stateOrProvinceName = match 74 | organizationName = match 75 | organizationalUnitName = optional 76 | commonName = supplied 77 | name = optional 78 | emailAddress = optional 79 | 80 | # For the 'anything' policy 81 | # At this point in time, you must list all acceptable 'object' 82 | # types. 83 | [ policy_anything ] 84 | countryName = optional 85 | stateOrProvinceName = optional 86 | localityName = optional 87 | organizationName = optional 88 | organizationalUnitName = optional 89 | commonName = supplied 90 | name = optional 91 | emailAddress = optional 92 | 93 | #################################################################### 94 | [ req ] 95 | default_bits = $ENV::KEY_SIZE 96 | default_keyfile = privkey.pem 97 | default_md = sha256 98 | distinguished_name = req_distinguished_name 99 | attributes = req_attributes 100 | x509_extensions = v3_ca # The extentions to add to the self signed cert 101 | 102 | # Passwords for private keys if not present they will be prompted for 103 | # input_password = secret 104 | # output_password = secret 105 | 106 | # This sets a mask for permitted string types. There are several options. 107 | # default: PrintableString, T61String, BMPString. 108 | # pkix : PrintableString, BMPString. 109 | # utf8only: only UTF8Strings. 110 | # nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). 111 | # MASK:XXXX a literal mask value. 112 | # WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings 113 | # so use this option with caution! 114 | string_mask = nombstr 115 | 116 | # req_extensions = v3_req # The extensions to add to a certificate request 117 | 118 | [ req_distinguished_name ] 119 | countryName = Country Name (2 letter code) 120 | countryName_default = $ENV::KEY_COUNTRY 121 | countryName_min = 2 122 | countryName_max = 2 123 | 124 | stateOrProvinceName = State or Province Name (full name) 125 | stateOrProvinceName_default = $ENV::KEY_PROVINCE 126 | 127 | localityName = Locality Name (eg, city) 128 | localityName_default = $ENV::KEY_CITY 129 | 130 | 0.organizationName = Organization Name (eg, company) 131 | 0.organizationName_default = $ENV::KEY_ORG 132 | 133 | # we can do this but it is not needed normally :-) 134 | #1.organizationName = Second Organization Name (eg, company) 135 | #1.organizationName_default = World Wide Web Pty Ltd 136 | 137 | organizationalUnitName = Organizational Unit Name (eg, section) 138 | #organizationalUnitName_default = 139 | 140 | commonName = Common Name (eg, your name or your server\'s hostname) 141 | commonName_max = 64 142 | 143 | name = Name 144 | name_max = 64 145 | 146 | emailAddress = Email Address 147 | emailAddress_default = $ENV::KEY_EMAIL 148 | emailAddress_max = 40 149 | 150 | # JY -- added for batch mode 151 | organizationalUnitName_default = $ENV::KEY_OU 152 | commonName_default = $ENV::KEY_CN 153 | name_default = $ENV::KEY_NAME 154 | 155 | # SET-ex3 = SET extension number 3 156 | 157 | [ req_attributes ] 158 | challengePassword = A challenge password 159 | challengePassword_min = 4 160 | challengePassword_max = 20 161 | 162 | unstructuredName = An optional company name 163 | 164 | [ usr_cert ] 165 | 166 | # These extensions are added when 'ca' signs a request. 167 | 168 | # This goes against PKIX guidelines but some CAs do it and some software 169 | # requires this to avoid interpreting an end user certificate as a CA. 170 | 171 | basicConstraints=CA:FALSE 172 | 173 | # Here are some examples of the usage of nsCertType. If it is omitted 174 | # the certificate can be used for anything *except* object signing. 175 | 176 | # This is OK for an SSL server. 177 | # nsCertType = server 178 | 179 | # For an object signing certificate this would be used. 180 | # nsCertType = objsign 181 | 182 | # For normal client use this is typical 183 | # nsCertType = client, email 184 | 185 | # and for everything including object signing: 186 | # nsCertType = client, email, objsign 187 | 188 | # This is typical in keyUsage for a client certificate. 189 | # keyUsage = nonRepudiation, digitalSignature, keyEncipherment 190 | 191 | # This will be displayed in Netscape's comment listbox. 192 | nsComment = "Easy-RSA Generated Certificate" 193 | 194 | # PKIX recommendations harmless if included in all certificates. 195 | subjectKeyIdentifier=hash 196 | authorityKeyIdentifier=keyid,issuer:always 197 | extendedKeyUsage=clientAuth 198 | keyUsage = digitalSignature 199 | 200 | # This stuff is for subjectAltName and issuerAltname. 201 | # Import the email address. 202 | # subjectAltName=email:copy 203 | subjectAltName=$ENV::KEY_ALTNAMES 204 | 205 | # Copy subject details 206 | # issuerAltName=issuer:copy 207 | 208 | #nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem 209 | #nsBaseUrl 210 | #nsRevocationUrl 211 | #nsRenewalUrl 212 | #nsCaPolicyUrl 213 | #nsSslServerName 214 | 215 | [ server ] 216 | 217 | # JY ADDED -- Make a cert with nsCertType set to "server" 218 | basicConstraints=CA:FALSE 219 | nsCertType = server 220 | nsComment = "Easy-RSA Generated Server Certificate" 221 | subjectKeyIdentifier=hash 222 | authorityKeyIdentifier=keyid,issuer:always 223 | extendedKeyUsage=serverAuth 224 | keyUsage = digitalSignature, keyEncipherment 225 | subjectAltName=$ENV::KEY_ALTNAMES 226 | 227 | [ v3_req ] 228 | 229 | # Extensions to add to a certificate request 230 | 231 | basicConstraints = CA:FALSE 232 | keyUsage = nonRepudiation, digitalSignature, keyEncipherment 233 | 234 | [ v3_ca ] 235 | 236 | 237 | # Extensions for a typical CA 238 | 239 | 240 | # PKIX recommendation. 241 | 242 | subjectKeyIdentifier=hash 243 | 244 | authorityKeyIdentifier=keyid:always,issuer:always 245 | 246 | # This is what PKIX recommends but some broken software chokes on critical 247 | # extensions. 248 | #basicConstraints = critical,CA:true 249 | # So we do this instead. 250 | basicConstraints = CA:true 251 | 252 | # Key usage: this is typical for a CA certificate. However since it will 253 | # prevent it being used as an test self-signed certificate it is best 254 | # left out by default. 255 | # keyUsage = cRLSign, keyCertSign 256 | 257 | # Some might want this also 258 | # nsCertType = sslCA, emailCA 259 | 260 | # Include email address in subject alt name: another PKIX recommendation 261 | # subjectAltName=email:copy 262 | # Copy issuer details 263 | # issuerAltName=issuer:copy 264 | 265 | # DER hex encoding of an extension: beware experts only! 266 | # obj=DER:02:03 267 | # Where 'obj' is a standard or added object 268 | # You can even override a supported extension: 269 | # basicConstraints= critical, DER:30:03:01:01:FF 270 | 271 | [ crl_ext ] 272 | 273 | # CRL extensions. 274 | # Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. 275 | 276 | # issuerAltName=issuer:copy 277 | authorityKeyIdentifier=keyid:always,issuer:always 278 | 279 | [ engine_section ] 280 | # 281 | # If you are using PKCS#11 282 | # Install engine_pkcs11 of opensc (www.opensc.org) 283 | # And uncomment the following 284 | # verify that dynamic_path points to the correct location 285 | # 286 | #pkcs11 = pkcs11_section 287 | 288 | [ pkcs11_section ] 289 | engine_id = pkcs11 290 | dynamic_path = /usr/lib/engines/engine_pkcs11.so 291 | MODULE_PATH = $ENV::PKCS11_MODULE_PATH 292 | PIN = $ENV::PKCS11_PIN 293 | init = 0 294 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/openssl-1.0.0.cnf: -------------------------------------------------------------------------------- 1 | # For use with easy-rsa version 2.0 2 | 3 | # 4 | # OpenSSL example configuration file. 5 | # This is mostly being used for generation of certificate requests. 6 | # 7 | 8 | # This definition stops the following lines choking if HOME isn't 9 | # defined. 10 | HOME = . 11 | RANDFILE = $ENV::HOME/.rnd 12 | openssl_conf = openssl_init 13 | 14 | [ openssl_init ] 15 | # Extra OBJECT IDENTIFIER info: 16 | #oid_file = $ENV::HOME/.oid 17 | oid_section = new_oids 18 | engines = engine_section 19 | 20 | # To use this configuration file with the "-extfile" option of the 21 | # "openssl x509" utility, name here the section containing the 22 | # X.509v3 extensions to use: 23 | # extensions = 24 | # (Alternatively, use a configuration file that has only 25 | # X.509v3 extensions in its main [= default] section.) 26 | 27 | [ new_oids ] 28 | 29 | # We can add new OIDs in here for use by 'ca' and 'req'. 30 | # Add a simple OID like this: 31 | # testoid1=1.2.3.4 32 | # Or use config file substitution like this: 33 | # testoid2=${testoid1}.5.6 34 | 35 | #################################################################### 36 | [ ca ] 37 | default_ca = CA_default # The default ca section 38 | 39 | #################################################################### 40 | [ CA_default ] 41 | 42 | dir = $ENV::KEY_DIR # Where everything is kept 43 | certs = $dir # Where the issued certs are kept 44 | crl_dir = $dir # Where the issued crl are kept 45 | database = $dir/index.txt # database index file. 46 | new_certs_dir = $dir # default place for new certs. 47 | 48 | certificate = $dir/ca.crt # The CA certificate 49 | serial = $dir/serial # The current serial number 50 | crl = $dir/crl.pem # The current CRL 51 | private_key = $dir/ca.key # The private key 52 | RANDFILE = $dir/.rand # private random number file 53 | 54 | x509_extensions = usr_cert # The extentions to add to the cert 55 | 56 | # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs 57 | # so this is commented out by default to leave a V1 CRL. 58 | # crl_extensions = crl_ext 59 | 60 | default_days = $ENV::CA_EXPIRE # how long to certify for 61 | default_crl_days = $ENV::CRL_EXPIRE # how long before next CRL 62 | default_md = sha256 # which md to use. 63 | preserve = no # keep passed DN ordering 64 | 65 | # A few difference way of specifying how similar the request should look 66 | # For type CA, the listed attributes must be the same, and the optional 67 | # and supplied fields are just that :-) 68 | policy = policy_anything 69 | 70 | # For the CA policy 71 | [ policy_match ] 72 | countryName = match 73 | stateOrProvinceName = match 74 | organizationName = match 75 | organizationalUnitName = optional 76 | commonName = supplied 77 | emailAddress = optional 78 | 79 | # For the 'anything' policy 80 | # At this point in time, you must list all acceptable 'object' 81 | # types. 82 | [ policy_anything ] 83 | countryName = optional 84 | stateOrProvinceName = optional 85 | localityName = optional 86 | organizationName = optional 87 | organizationalUnitName = optional 88 | commonName = supplied 89 | emailAddress = optional 90 | 91 | #################################################################### 92 | [ req ] 93 | default_bits = $ENV::KEY_SIZE 94 | default_keyfile = privkey.pem 95 | default_md = sha256 96 | distinguished_name = req_distinguished_name 97 | attributes = req_attributes 98 | x509_extensions = v3_ca # The extentions to add to the self signed cert 99 | 100 | # Passwords for private keys if not present they will be prompted for 101 | # input_password = secret 102 | # output_password = secret 103 | 104 | # This sets a mask for permitted string types. There are several options. 105 | # default: PrintableString, T61String, BMPString. 106 | # pkix : PrintableString, BMPString. 107 | # utf8only: only UTF8Strings. 108 | # nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). 109 | # MASK:XXXX a literal mask value. 110 | # WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings 111 | # so use this option with caution! 112 | string_mask = nombstr 113 | 114 | # req_extensions = v3_req # The extensions to add to a certificate request 115 | 116 | [ req_distinguished_name ] 117 | countryName = Country Name (2 letter code) 118 | countryName_default = $ENV::KEY_COUNTRY 119 | countryName_min = 2 120 | countryName_max = 2 121 | 122 | stateOrProvinceName = State or Province Name (full name) 123 | stateOrProvinceName_default = $ENV::KEY_PROVINCE 124 | 125 | localityName = Locality Name (eg, city) 126 | localityName_default = $ENV::KEY_CITY 127 | 128 | 0.organizationName = Organization Name (eg, company) 129 | 0.organizationName_default = $ENV::KEY_ORG 130 | 131 | # we can do this but it is not needed normally :-) 132 | #1.organizationName = Second Organization Name (eg, company) 133 | #1.organizationName_default = World Wide Web Pty Ltd 134 | 135 | organizationalUnitName = Organizational Unit Name (eg, section) 136 | #organizationalUnitName_default = 137 | 138 | commonName = Common Name (eg, your name or your server\'s hostname) 139 | commonName_max = 64 140 | 141 | emailAddress = Email Address 142 | emailAddress_default = $ENV::KEY_EMAIL 143 | emailAddress_max = 40 144 | 145 | # JY -- added for batch mode 146 | organizationalUnitName_default = $ENV::KEY_OU 147 | commonName_default = $ENV::KEY_CN 148 | 149 | # SET-ex3 = SET extension number 3 150 | 151 | [ req_attributes ] 152 | challengePassword = A challenge password 153 | challengePassword_min = 4 154 | challengePassword_max = 20 155 | 156 | unstructuredName = An optional company name 157 | 158 | [ usr_cert ] 159 | 160 | # These extensions are added when 'ca' signs a request. 161 | 162 | # This goes against PKIX guidelines but some CAs do it and some software 163 | # requires this to avoid interpreting an end user certificate as a CA. 164 | 165 | basicConstraints=CA:FALSE 166 | 167 | # Here are some examples of the usage of nsCertType. If it is omitted 168 | # the certificate can be used for anything *except* object signing. 169 | 170 | # This is OK for an SSL server. 171 | # nsCertType = server 172 | 173 | # For an object signing certificate this would be used. 174 | # nsCertType = objsign 175 | 176 | # For normal client use this is typical 177 | # nsCertType = client, email 178 | 179 | # and for everything including object signing: 180 | # nsCertType = client, email, objsign 181 | 182 | # This is typical in keyUsage for a client certificate. 183 | # keyUsage = nonRepudiation, digitalSignature, keyEncipherment 184 | 185 | # This will be displayed in Netscape's comment listbox. 186 | nsComment = "Easy-RSA Generated Certificate" 187 | 188 | # PKIX recommendations harmless if included in all certificates. 189 | subjectKeyIdentifier=hash 190 | authorityKeyIdentifier=keyid,issuer:always 191 | extendedKeyUsage=clientAuth 192 | keyUsage = digitalSignature 193 | 194 | # This stuff is for subjectAltName and issuerAltname. 195 | # Import the email address. 196 | # subjectAltName=email:copy 197 | 198 | # Copy subject details 199 | # issuerAltName=issuer:copy 200 | 201 | #nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem 202 | #nsBaseUrl 203 | #nsRevocationUrl 204 | #nsRenewalUrl 205 | #nsCaPolicyUrl 206 | #nsSslServerName 207 | 208 | [ server ] 209 | 210 | # JY ADDED -- Make a cert with nsCertType set to "server" 211 | basicConstraints=CA:FALSE 212 | nsCertType = server 213 | nsComment = "Easy-RSA Generated Server Certificate" 214 | subjectKeyIdentifier=hash 215 | authorityKeyIdentifier=keyid,issuer:always 216 | extendedKeyUsage=serverAuth 217 | keyUsage = digitalSignature, keyEncipherment 218 | 219 | [ v3_req ] 220 | 221 | # Extensions to add to a certificate request 222 | 223 | basicConstraints = CA:FALSE 224 | keyUsage = nonRepudiation, digitalSignature, keyEncipherment 225 | 226 | [ v3_ca ] 227 | 228 | 229 | # Extensions for a typical CA 230 | 231 | 232 | # PKIX recommendation. 233 | 234 | subjectKeyIdentifier=hash 235 | 236 | authorityKeyIdentifier=keyid:always,issuer:always 237 | 238 | # This is what PKIX recommends but some broken software chokes on critical 239 | # extensions. 240 | #basicConstraints = critical,CA:true 241 | # So we do this instead. 242 | basicConstraints = CA:true 243 | 244 | # Key usage: this is typical for a CA certificate. However since it will 245 | # prevent it being used as an test self-signed certificate it is best 246 | # left out by default. 247 | # keyUsage = cRLSign, keyCertSign 248 | 249 | # Some might want this also 250 | # nsCertType = sslCA, emailCA 251 | 252 | # Include email address in subject alt name: another PKIX recommendation 253 | # subjectAltName=email:copy 254 | # Copy issuer details 255 | # issuerAltName=issuer:copy 256 | 257 | # DER hex encoding of an extension: beware experts only! 258 | # obj=DER:02:03 259 | # Where 'obj' is a standard or added object 260 | # You can even override a supported extension: 261 | # basicConstraints= critical, DER:30:03:01:01:FF 262 | 263 | [ crl_ext ] 264 | 265 | # CRL extensions. 266 | # Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. 267 | 268 | # issuerAltName=issuer:copy 269 | authorityKeyIdentifier=keyid:always,issuer:always 270 | 271 | [ engine_section ] 272 | # 273 | # If you are using PKCS#11 274 | # Install engine_pkcs11 of opensc (www.opensc.org) 275 | # And uncomment the following 276 | # verify that dynamic_path points to the correct location 277 | # 278 | #pkcs11 = pkcs11_section 279 | 280 | #[ pkcs11_section ] 281 | #engine_id = pkcs11 282 | #dynamic_path = /usr/lib/engines/engine_pkcs11.so 283 | #MODULE_PATH = $ENV::PKCS11_MODULE_PATH 284 | #PIN = $ENV::PKCS11_PIN 285 | #init = 0 286 | 287 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/pem-split: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk -f 2 | # 3 | # Take a PEM format file as input and split out certs and keys into separate files 4 | # added TA keys spolitter by Tobi 5 | # Copyright, original file: https://gist.github.com/jinnko/d6867ce326e8b6e88975 6 | 7 | 8 | BEGIN { n=0; cert=0; key=0; if ( ARGC < 2 ) { print "Usage: pem-split FILENAME"; exit 1 } } 9 | /-----BEGIN PRIVATE KEY-----/ { key=1; cert=0 } 10 | /-----BEGIN OpenVPN Static key V1-----/ { key=1; cert=0 } 11 | /-----BEGIN CERTIFICATE-----/ { cert=1; key=0 } 12 | split_after == 1 { n++; split_after=0 } 13 | /-----END CERTIFICATE-----/ { split_after=1 } 14 | /-----END PRIVATE KEY-----/ { split_after=1 } 15 | /-----END OpenVPN Static key V1-----/ { split_after=1 } 16 | key == 1 { print > FILENAME "-" n ".key" } 17 | cert == 1 { print > FILENAME "-" n ".crt" } 18 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/pkitool: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # OpenVPN -- An application to securely tunnel IP networks 4 | # over a single TCP/UDP port, with support for SSL/TLS-based 5 | # session authentication and key exchange, 6 | # packet encryption, packet authentication, and 7 | # packet compression. 8 | # 9 | # Copyright (C) 2002-2010 OpenVPN Technologies, Inc. 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License version 2 13 | # as published by the Free Software Foundation. 14 | # 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program (see the file COPYING included with this 22 | # distribution); if not, write to the Free Software Foundation, Inc., 23 | # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | # pkitool is a front-end for the openssl tool. 26 | 27 | # Calling scripts can set the certificate organizational 28 | # unit with the KEY_OU environmental variable. 29 | 30 | # Calling scripts can also set the KEY_NAME environmental 31 | # variable to set the "name" X509 subject field. 32 | 33 | PROGNAME=pkitool 34 | VERSION=2.0 35 | DEBUG=0 36 | 37 | die() 38 | { 39 | local m="$1" 40 | 41 | echo "$m" >&2 42 | exit 1 43 | } 44 | 45 | need_vars() 46 | { 47 | cat < root certificate (--ca) 100 | ca.key -> root key, keep secure (not directly used by OpenVPN) 101 | .crt files -> client/server certificates (--cert) 102 | .key files -> private keys, keep secure (--key) 103 | .csr files -> certificate signing request (not directly used by OpenVPN) 104 | dh1024.pem or dh2048.pem -> Diffie Hellman parameters (--dh) 105 | 106 | Examples: 107 | $PROGNAME --initca -> Build root certificate 108 | $PROGNAME --initca --pass -> Build root certificate with password-protected key 109 | $PROGNAME --server server1 -> Build "server1" certificate/key 110 | $PROGNAME client1 -> Build "client1" certificate/key 111 | $PROGNAME --pass client2 -> Build password-protected "client2" certificate/key 112 | $PROGNAME --pkcs12 client3 -> Build "client3" certificate/key in PKCS#12 format 113 | $PROGNAME --csr client4 -> Build "client4" CSR to be signed by another CA 114 | $PROGNAME --sign client4 -> Sign "client4" CSR 115 | $PROGNAME --inter interca -> Build an intermediate key-signing certificate/key 116 | Also see ./inherit-inter script. 117 | $PROGNAME --pkcs11 /usr/lib/pkcs11/lib1 0 010203 "client5 id" client5 118 | -> Build "client5" certificate/key in PKCS#11 token 119 | 120 | Typical usage for initial PKI setup. Build myserver, client1, and client2 cert/keys. 121 | Protect client2 key with a password. Build DH parms. Generated files in ./keys : 122 | [edit vars with your site-specific info] 123 | source ./vars 124 | ./clean-all 125 | ./build-dh -> takes a long time, consider backgrounding 126 | ./$PROGNAME --initca 127 | ./$PROGNAME --server myserver 128 | ./$PROGNAME client1 129 | ./$PROGNAME --pass client2 130 | 131 | Typical usage for adding client cert to existing PKI: 132 | source ./vars 133 | ./$PROGNAME client-new 134 | EOM 135 | } 136 | 137 | # Set tool defaults 138 | [ -n "$OPENSSL" ] || export OPENSSL="openssl" 139 | [ -n "$PKCS11TOOL" ] || export PKCS11TOOL="pkcs11-tool" 140 | [ -n "$GREP" ] || export GREP="grep" 141 | 142 | # Set defaults 143 | DO_REQ="1" 144 | REQ_EXT="" 145 | DO_CA="1" 146 | CA_EXT="" 147 | DO_P12="0" 148 | DO_P11="0" 149 | DO_ROOT="0" 150 | NODES_REQ="-nodes" 151 | NODES_P12="" 152 | BATCH="-batch" 153 | CA="ca" 154 | # must be set or errors of openssl.cnf 155 | PKCS11_MODULE_PATH="dummy" 156 | PKCS11_PIN="dummy" 157 | 158 | # Process options 159 | while [ $# -gt 0 ]; do 160 | case "$1" in 161 | --keysize ) KEY_SIZE=$2 162 | shift;; 163 | --server ) REQ_EXT="$REQ_EXT -extensions server" 164 | CA_EXT="$CA_EXT -extensions server" ;; 165 | --batch ) BATCH="-batch" ;; 166 | --interact ) BATCH="" ;; 167 | --inter ) CA_EXT="$CA_EXT -extensions v3_ca" ;; 168 | --initca ) DO_ROOT="1" ;; 169 | --pass ) NODES_REQ="" ;; 170 | --csr ) DO_CA="0" ;; 171 | --sign ) DO_REQ="0" ;; 172 | --pkcs12 ) DO_P12="1" ;; 173 | --pkcs11 ) DO_P11="1" 174 | PKCS11_MODULE_PATH="$2" 175 | PKCS11_SLOT="$3" 176 | PKCS11_ID="$4" 177 | PKCS11_LABEL="$5" 178 | shift 4;; 179 | 180 | # standalone 181 | --pkcs11-init) 182 | PKCS11_MODULE_PATH="$2" 183 | PKCS11_SLOT="$3" 184 | PKCS11_LABEL="$4" 185 | if [ -z "$PKCS11_LABEL" ]; then 186 | die "Please specify library name, slot and label" 187 | fi 188 | $PKCS11TOOL --module "$PKCS11_MODULE_PATH" --init-token --slot "$PKCS11_SLOT" \ 189 | --label "$PKCS11_LABEL" && 190 | $PKCS11TOOL --module "$PKCS11_MODULE_PATH" --init-pin --slot "$PKCS11_SLOT" 191 | exit $?;; 192 | --pkcs11-slots) 193 | PKCS11_MODULE_PATH="$2" 194 | if [ -z "$PKCS11_MODULE_PATH" ]; then 195 | die "Please specify library name" 196 | fi 197 | $PKCS11TOOL --module "$PKCS11_MODULE_PATH" --list-slots 198 | exit 0;; 199 | --pkcs11-objects) 200 | PKCS11_MODULE_PATH="$2" 201 | PKCS11_SLOT="$3" 202 | if [ -z "$PKCS11_SLOT" ]; then 203 | die "Please specify library name and slot" 204 | fi 205 | $PKCS11TOOL --module "$PKCS11_MODULE_PATH" --list-objects --login --slot "$PKCS11_SLOT" 206 | exit 0;; 207 | 208 | --help|--usage) 209 | usage 210 | exit ;; 211 | --version) 212 | echo "$PROGNAME $VERSION" 213 | exit ;; 214 | # errors 215 | --* ) die "$PROGNAME: unknown option: $1" ;; 216 | * ) break ;; 217 | esac 218 | shift 219 | done 220 | 221 | if ! [ -z "$BATCH" ]; then 222 | if $OPENSSL version | grep 0.9.6 > /dev/null; then 223 | die "Batch mode is unsupported in openssl<0.9.7" 224 | fi 225 | fi 226 | 227 | if [ $DO_P12 -eq 1 -a $DO_P11 -eq 1 ]; then 228 | die "PKCS#11 and PKCS#12 cannot be specified together" 229 | fi 230 | 231 | if [ $DO_P11 -eq 1 ]; then 232 | if ! grep "^pkcs11.*=" "$KEY_CONFIG" > /dev/null; then 233 | die "Please edit $KEY_CONFIG and setup PKCS#11 engine" 234 | fi 235 | fi 236 | 237 | # If we are generating pkcs12, only encrypt the final step 238 | if [ $DO_P12 -eq 1 ]; then 239 | NODES_P12="$NODES_REQ" 240 | NODES_REQ="-nodes" 241 | fi 242 | 243 | if [ $DO_P11 -eq 1 ]; then 244 | if [ -z "$PKCS11_LABEL" ]; then 245 | die "PKCS#11 arguments incomplete" 246 | fi 247 | fi 248 | 249 | # If undefined, set default key expiration intervals 250 | if [ -z "$KEY_EXPIRE" ]; then 251 | KEY_EXPIRE=3650 252 | fi 253 | if [ -z "$CA_EXPIRE" ]; then 254 | CA_EXPIRE=3650 255 | fi 256 | 257 | # Set organizational unit to empty string if undefined 258 | if [ -z "$KEY_OU" ]; then 259 | KEY_OU="" 260 | fi 261 | 262 | # Set X509 Name string to empty string if undefined 263 | if [ -z "$KEY_NAME" ]; then 264 | KEY_NAME="" 265 | fi 266 | 267 | # Set KEY_CN, FN 268 | if [ $DO_ROOT -eq 1 ]; then 269 | if [ -z "$KEY_CN" ]; then 270 | if [ "$1" ]; then 271 | KEY_CN="$1" 272 | KEY_ALTNAMES="DNS:${KEY_CN}" 273 | elif [ "$KEY_ORG" ]; then 274 | KEY_CN="$KEY_ORG CA" 275 | KEY_ALTNAMES="$KEY_CN" 276 | fi 277 | fi 278 | if [ $BATCH ] && [ "$KEY_CN" ]; then 279 | echo "Using CA Common Name:" "$KEY_CN" 280 | KEY_ALTNAMES="$KEY_CN" 281 | fi 282 | FN="$KEY_CN" 283 | elif [ $BATCH ] && [ "$KEY_CN" ]; then 284 | echo "Using Common Name:" "$KEY_CN" 285 | KEY_ALTNAMES="$KEY_CN" 286 | FN="$KEY_CN" 287 | if [ "$1" ]; then 288 | FN="$1" 289 | fi 290 | else 291 | KEY_CN="$1" 292 | KEY_ALTNAMES="DNS:$1" 293 | shift 294 | while [ "x$1" != "x" ] 295 | do 296 | KEY_ALTNAMES="${KEY_ALTNAMES},DNS:$1" 297 | shift 298 | done 299 | FN="$KEY_CN" 300 | fi 301 | 302 | export CA_EXPIRE KEY_EXPIRE KEY_OU KEY_NAME KEY_CN PKCS11_MODULE_PATH PKCS11_PIN KEY_ALTNAMES 303 | 304 | # Show parameters (debugging) 305 | if [ $DEBUG -eq 1 ]; then 306 | echo DO_REQ $DO_REQ 307 | echo REQ_EXT $REQ_EXT 308 | echo DO_CA $DO_CA 309 | echo CA_EXT $CA_EXT 310 | echo NODES_REQ $NODES_REQ 311 | echo NODES_P12 $NODES_P12 312 | echo DO_P12 $DO_P12 313 | echo KEY_CN $KEY_CN 314 | echo KEY_ALTNAMES $KEY_ALTNAMES 315 | echo BATCH $BATCH 316 | echo DO_ROOT $DO_ROOT 317 | echo KEY_EXPIRE $KEY_EXPIRE 318 | echo CA_EXPIRE $CA_EXPIRE 319 | echo KEY_OU $KEY_OU 320 | echo KEY_NAME $KEY_NAME 321 | echo DO_P11 $DO_P11 322 | echo PKCS11_MODULE_PATH $PKCS11_MODULE_PATH 323 | echo PKCS11_SLOT $PKCS11_SLOT 324 | echo PKCS11_ID $PKCS11_ID 325 | echo PKCS11_LABEL $PKCS11_LABEL 326 | fi 327 | 328 | # Make sure ./vars was sourced beforehand 329 | if [ -d "$KEY_DIR" ] && [ "$KEY_CONFIG" ]; then 330 | cd "$KEY_DIR" 331 | 332 | # Make sure $KEY_CONFIG points to the correct version 333 | # of openssl.cnf 334 | if $GREP -i 'easy-rsa version 2\.[0-9]' "$KEY_CONFIG" >/dev/null; then 335 | : 336 | else 337 | echo "$PROGNAME: KEY_CONFIG (set by the ./vars script) is pointing to the wrong" 338 | echo "version of openssl.cnf: $KEY_CONFIG" 339 | echo "The correct version should have a comment that says: easy-rsa version 2.x"; 340 | exit 1; 341 | fi 342 | 343 | # Build root CA 344 | if [ $DO_ROOT -eq 1 ]; then 345 | $OPENSSL req $BATCH -days $CA_EXPIRE $NODES_REQ -new -newkey rsa:$KEY_SIZE \ 346 | -x509 -keyout "$CA.key" -out "$CA.crt" -config "$KEY_CONFIG" && \ 347 | chmod 0600 "$CA.key" 348 | else 349 | # Make sure CA key/cert is available 350 | if [ $DO_CA -eq 1 ] || [ $DO_P12 -eq 1 ]; then 351 | if [ ! -r "$CA.crt" ] || [ ! -r "$CA.key" ]; then 352 | echo "$PROGNAME: Need a readable $CA.crt and $CA.key in $KEY_DIR" 353 | echo "Try $PROGNAME --initca to build a root certificate/key." 354 | exit 1 355 | fi 356 | fi 357 | 358 | # Generate key for PKCS#11 token 359 | PKCS11_ARGS= 360 | if [ $DO_P11 -eq 1 ]; then 361 | stty -echo 362 | echo -n "User PIN: " 363 | read -r PKCS11_PIN 364 | stty echo 365 | export PKCS11_PIN 366 | 367 | echo "Generating key pair on PKCS#11 token..." 368 | $PKCS11TOOL --module "$PKCS11_MODULE_PATH" --keypairgen \ 369 | --login --pin "$PKCS11_PIN" \ 370 | --key-type rsa:1024 \ 371 | --slot "$PKCS11_SLOT" --id "$PKCS11_ID" --label "$PKCS11_LABEL" || exit 1 372 | PKCS11_ARGS="-engine pkcs11 -keyform engine -key $PKCS11_SLOT:$PKCS11_ID" 373 | fi 374 | 375 | # Build cert/key 376 | ( [ $DO_REQ -eq 0 ] || $OPENSSL req $BATCH $NODES_REQ -new -newkey rsa:$KEY_SIZE \ 377 | -keyout "$FN.key" -out "$FN.csr" $REQ_EXT -config "$KEY_CONFIG" $PKCS11_ARGS ) && \ 378 | ( [ $DO_CA -eq 0 ] || $OPENSSL ca $BATCH -days $KEY_EXPIRE -out "$FN.crt" \ 379 | -in "$FN.csr" $CA_EXT -config "$KEY_CONFIG" ) && \ 380 | ( [ $DO_P12 -eq 0 ] || $OPENSSL pkcs12 -export -inkey "$FN.key" \ 381 | -in "$FN.crt" -certfile "$CA.crt" -out "$FN.p12" $NODES_P12 ) && \ 382 | ( [ $DO_CA -eq 0 -o $DO_P11 -eq 1 ] || chmod 0600 "$FN.key" ) && \ 383 | ( [ $DO_P12 -eq 0 ] || chmod 0600 "$FN.p12" ) 384 | 385 | # Load certificate into PKCS#11 token 386 | if [ $DO_P11 -eq 1 ]; then 387 | $OPENSSL x509 -in "$FN.crt" -inform PEM -out "$FN.crt.der" -outform DER && \ 388 | $PKCS11TOOL --module "$PKCS11_MODULE_PATH" --write-object "$FN.crt.der" --type cert \ 389 | --login --pin "$PKCS11_PIN" \ 390 | --slot "$PKCS11_SLOT" --id "$PKCS11_ID" --label "$PKCS11_LABEL" 391 | [ -e "$FN.crt.der" ]; rm "$FN.crt.der" 392 | fi 393 | 394 | fi 395 | 396 | # Need definitions 397 | else 398 | need_vars 399 | fi 400 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/revoke-client: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # revoke a certificate, regenerate CRL, 4 | # and verify revocation 5 | 6 | source ./vars 7 | 8 | CRL="crl.pem" 9 | RT="revoke-test.pem" 10 | 11 | if [ $# -ne 1 ]; then 12 | echo "usage: revoke-full "; 13 | exit 1 14 | fi 15 | 16 | if [ "$KEY_DIR" ]; then 17 | echo "Revoking OpenVPN certificate: $1" 18 | cd "$KEY_DIR" 19 | rm -f "$RT" 20 | 21 | # set defaults 22 | export KEY_CN="" 23 | export KEY_OU="" 24 | 25 | # revoke key and generate a new CRL 26 | $OPENSSL ca -revoke "$1/$1.crt" -config "$KEY_CONFIG" 27 | 28 | echo "." 29 | # generate a new CRL -- try to be compatible with 30 | # intermediate PKIs 31 | $OPENSSL ca -gencrl -out "$CRL" -config "$KEY_CONFIG" 32 | if [ -e export-ca.crt ]; then 33 | cat export-ca.crt "$CRL" >"$RT" 34 | else 35 | cat ca.crt "$CRL" >"$RT" 36 | fi 37 | echo "." 38 | echo "Verify the revocation:" 39 | # verify the revocation 40 | $OPENSSL verify -CAfile "$RT" -crl_check "$1/$1.crt" 41 | echo "DONE." 42 | else 43 | echo 'Please source the vars script first (i.e. "source ./vars")' 44 | echo 'Make sure you have edited it to reflect your configuration.' 45 | fi 46 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/server-startup-template-tcp-gw.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | main_interface=`ip r sh | grep default | awk '{print $5}'` 4 | 5 | iptables -t nat -A POSTROUTING -s 10.8.3.0/24 -o ${main_interface} -j MASQUERADE 6 | echo 1 > /proc/sys/net/ipv4/ip_forward 7 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/server-startup-template.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | main_interface=`ip r sh | grep default | awk '{print $5}'` 4 | 5 | iptables -t nat -A POSTROUTING -s 10.8.2.0/24 -o ${main_interface} -j MASQUERADE 6 | echo 1 > /proc/sys/net/ipv4/ip_forward 7 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/server-template-tcp-commongw.conf: -------------------------------------------------------------------------------- 1 | dev tun1 2 | port CHANGE_PORT 3 | proto tcp-server 4 | 5 | mode server 6 | tls-server 7 | 8 | ca /etc/openvpn/keys/ca.crt 9 | cert /etc/openvpn/keys/server.crt 10 | key /etc/openvpn/keys/server.key 11 | dh /etc/openvpn/keys/dh2048.pem 12 | tls-auth /etc/openvpn/keys/ta.key 0 13 | crl-verify /etc/openvpn/keys/crl.pem 14 | 15 | reneg-sec 86400 16 | cipher AES-256-CBC 17 | 18 | client-config-dir /etc/openvpn/ccd 19 | ifconfig-pool-persist /etc/openvpn/ipp.txt 20 | 21 | ifconfig 10.8.3.1 10.8.3.2 22 | ifconfig-pool 10.8.3.3 10.8.3.250 23 | route 10.8.3.0 255.255.255.0 24 | client-to-client 25 | 26 | push "route 10.8.3.0 255.255.255.0" 27 | push "redirect-gateway def1" 28 | push "dhcp-option DNS 8.8.4.4" 29 | 30 | ### extra push routes here 31 | ###push "route 10.0.0.0 255.255.0.0" 32 | ### push dns here 33 | ###push "register-dns" 34 | ###push "dhcp-option DNS 10.0.0.10" 35 | ###push "dhcp-option DOMAIN example.com" 36 | 37 | status /var/log/openvpn/openvpn-tcp-gw-status.log 38 | log /var/log/openvpn/openvpn-tcp-gw.log 39 | 40 | mute-replay-warnings 41 | user nobody 42 | group nogroup 43 | mute 20 44 | max-clients 255 45 | keepalive 10 60 46 | ping-timer-rem 47 | 48 | persist-key 49 | persist-tun 50 | 51 | ### startup script here (routing) 52 | script-security 2 53 | up /etc/openvpn/server-tcp-gw-startup.sh 54 | verb 3 55 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/server-template.conf: -------------------------------------------------------------------------------- 1 | dev tun0 2 | port CHANGE_PORT 3 | proto udp 4 | 5 | mode server 6 | tls-server 7 | 8 | ca /etc/openvpn/keys/ca.crt 9 | cert /etc/openvpn/keys/server.crt 10 | key /etc/openvpn/keys/server.key 11 | dh /etc/openvpn/keys/dh2048.pem 12 | tls-auth /etc/openvpn/keys/ta.key 0 13 | crl-verify /etc/openvpn/keys/crl.pem 14 | 15 | reneg-sec 86400 16 | cipher AES-256-CBC 17 | 18 | client-config-dir /etc/openvpn/ccd 19 | ifconfig-pool-persist /etc/openvpn/ipp.txt 20 | 21 | ifconfig 10.8.2.1 10.8.2.2 22 | ifconfig-pool 10.8.2.3 10.8.2.250 23 | route 10.8.2.0 255.255.255.0 24 | client-to-client 25 | 26 | push "route 10.8.2.0 255.255.255.0" 27 | 28 | ### extra push routes here 29 | ###push "route 10.0.0.0 255.255.0.0" 30 | ### push dns here 31 | ###push "register-dns" 32 | ###push "dhcp-option DNS 8.8.8.8" 33 | ###push "dhcp-option DOMAIN example.com" 34 | 35 | status /var/log/openvpn/openvpn-status.log 36 | log /var/log/openvpn/openvpn.log 37 | 38 | mute-replay-warnings 39 | user nobody 40 | group nogroup 41 | mute 20 42 | max-clients 255 43 | keepalive 10 60 44 | ping-timer-rem 45 | 46 | persist-key 47 | persist-tun 48 | 49 | ### startup script here (routing) 50 | script-security 2 51 | up /etc/openvpn/server-startup.sh 52 | verb 3 53 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/sign-req: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Sign a certificate signing request (a .csr file) 4 | # with a local root certificate and key. 5 | 6 | source ./vars 7 | 8 | if [[ -e $KEY_DIR/server.csr ]]; 9 | then 10 | echo "WARNING:server.csr already exists! Exit." 11 | exit 1 12 | fi 13 | 14 | export EASY_RSA="${EASY_RSA:-.}" 15 | "$EASY_RSA/pkitool" --interact --sign $* 16 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/vars: -------------------------------------------------------------------------------- 1 | # easy-rsa parameter settings 2 | 3 | # NOTE: If you installed from an RPM, 4 | # don't edit this file in place in 5 | # /usr/share/openvpn/easy-rsa -- 6 | # instead, you should copy the whole 7 | # easy-rsa directory to another location 8 | # (such as /etc/openvpn) so that your 9 | # edits will not be wiped out by a future 10 | # OpenVPN package upgrade. 11 | 12 | # This variable should point to 13 | # the top level of the easy-rsa 14 | # tree. 15 | export EASY_RSA="`pwd`" 16 | 17 | # 18 | # This variable should point to 19 | # the requested executables 20 | # 21 | export OPENSSL="openssl" 22 | export PKCS11TOOL="pkcs11-tool" 23 | export GREP="grep" 24 | 25 | # This variable should point to 26 | # the openssl.cnf file included 27 | # with easy-rsa. 28 | export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA` 29 | 30 | # Edit this variable to point to 31 | # your soon-to-be-created key 32 | # directory. 33 | # 34 | # WARNING: clean-all will do 35 | # a rm -rf on this directory 36 | # so make sure you define 37 | # it correctly! 38 | 39 | # Issue rm -rf warning 40 | #echo NOTE: If you run ./clean-all, I will be doing a rm -rf on $KEY_DIR 41 | 42 | #export KEY_CN="" 43 | # In how many days should the root CA key expire? 44 | # In how many days should certificates expire? 45 | # These are the default values for fields 46 | # which will be placed in the certificate. 47 | # Don't leave any of these fields blank. 48 | 49 | 50 | ############################################ 51 | # Configure these fields 52 | ############################################ 53 | export OPENVPN_CONF_DIR="/etc/openvpn" 54 | export OPENVPN_LOG_DIR="/var/log/openvpn" 55 | export KEY_SIZE=2048 56 | export CA_EXPIRE=7300 57 | export KEY_EXPIRE=7300 58 | export CRL_EXPIRE=7300 59 | export KEY_COUNTRY="CC" 60 | export KEY_PROVINCE="CHANGE_PROVINCE" 61 | export KEY_CITY="CHANGE_CITY" 62 | export KEY_ORG="CHANGE_ORG" 63 | export KEY_EMAIL="CHANGE_ORG_EMAIL" 64 | export KEY_OU="CHANGE_OU" 65 | export SERVER_ENDPOINT="CHANGE_SERVER_IP" 66 | export SERVER_PORT_TCP="443" 67 | export SERVER_PORT_UDP="1194" 68 | export KEY_DIR="$OPENVPN_CONF_DIR/keys" 69 | -------------------------------------------------------------------------------- /easy-openvpn/keygen/whichopensslcnf: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | 4 | cnf="$1/openssl.cnf" 5 | 6 | if [ "$OPENSSL" ]; then 7 | if $OPENSSL version | grep -E "0\.9\.6[[:alnum:]]?" > /dev/null; then 8 | cnf="$1/openssl-0.9.6.cnf" 9 | elif $OPENSSL version | grep -E "0\.9\.8[[:alnum:]]?" > /dev/null; then 10 | cnf="$1/openssl-0.9.8.cnf" 11 | elif $OPENSSL version | grep -E "1\.0\.[[:digit:]][[:alnum:]]?" > /dev/null; then 12 | cnf="$1/openssl-1.0.0.cnf" 13 | else 14 | cnf="$1/openssl.cnf" 15 | fi 16 | fi 17 | 18 | echo $cnf 19 | 20 | if [ ! -r $cnf ]; then 21 | echo "**************************************************************" >&2 22 | echo " No $cnf file could be found" >&2 23 | echo " Further invocations will fail" >&2 24 | echo "**************************************************************" >&2 25 | fi 26 | 27 | exit 0 28 | --------------------------------------------------------------------------------