├── .gitignore ├── LICENSE ├── README.md ├── application ├── README.md ├── akka │ ├── README.md │ ├── java │ │ ├── Dockerfile │ │ └── example │ │ │ ├── build.gradle │ │ │ ├── build.sbt │ │ │ ├── pom.xml │ │ │ ├── project │ │ │ ├── build.properties │ │ │ └── plugins.sbt │ │ │ └── src │ │ │ ├── main │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── Example.java │ │ │ └── resources │ │ │ │ ├── application.conf │ │ │ │ └── logback.xml │ │ │ └── test │ │ │ └── resources │ │ │ └── application-test.conf │ └── scala │ │ ├── Dockerfile │ │ └── example │ │ ├── .gitignore │ │ ├── build.sbt │ │ ├── project │ │ ├── build.properties │ │ └── plugins.sbt │ │ └── src │ │ ├── main │ │ ├── resources │ │ │ ├── application.conf │ │ │ └── logback.xml │ │ └── scala │ │ │ └── com │ │ │ └── example │ │ │ └── Example.scala │ │ └── test │ │ └── resources │ │ └── application-test.conf ├── aspnet │ ├── cli-example │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── aspnetapp.sln │ │ └── example │ │ │ ├── Pages │ │ │ ├── Index.cshtml │ │ │ ├── Index.cshtml.cs │ │ │ └── _ViewImports.cshtml │ │ │ ├── Program.cs │ │ │ ├── Properties │ │ │ └── launchSettings.json │ │ │ ├── Startup.cs │ │ │ ├── appsettings.Development.json │ │ │ ├── appsettings.json │ │ │ └── example.csproj │ └── sdk-example │ │ ├── Dockerfile │ │ ├── README.md │ │ └── example │ │ ├── Pages │ │ ├── Index.cshtml │ │ └── Index.cshtml.cs │ │ └── example.csproj ├── django │ ├── Dockerfile │ ├── README.md │ ├── requirements.txt │ ├── urls.py │ └── views.py ├── flask │ ├── Dockerfile │ ├── README.md │ ├── app.py │ └── requirements.txt ├── kitura │ ├── Dockerfile │ ├── HelloKitura │ │ ├── Package.swift │ │ └── Sources │ │ │ └── HelloKitura │ │ │ └── main.swift │ └── README.md ├── nodejs │ ├── Dockerfile │ ├── README.md │ ├── index.js │ ├── package-lock.json │ └── package.json ├── perfect │ ├── Dockerfile │ ├── PerfectTemplate │ │ └── Sources │ │ │ └── PerfectTemplate │ │ │ └── main.swift │ └── README.md ├── phoenix │ ├── Dockerfile │ ├── README.md │ └── example │ │ ├── controllers │ │ └── example_controller.ex │ │ └── router.ex ├── play │ ├── README.md │ ├── java │ │ ├── Dockerfile │ │ └── example │ │ │ ├── .gitignore │ │ │ ├── app │ │ │ └── controllers │ │ │ │ └── HomeController.java │ │ │ ├── build.sbt │ │ │ ├── conf │ │ │ ├── application.conf │ │ │ ├── logback.xml │ │ │ └── routes │ │ │ ├── project │ │ │ ├── build.properties │ │ │ └── plugins.sbt │ │ │ └── test │ │ │ └── controllers │ │ │ └── HomeControllerTest.java │ └── scala │ │ ├── Dockerfile │ │ └── example │ │ ├── .gitignore │ │ ├── app │ │ └── controllers │ │ │ └── HomeController.scala │ │ ├── build.sbt │ │ ├── conf │ │ ├── application.conf │ │ ├── logback.xml │ │ ├── messages │ │ └── routes │ │ ├── project │ │ ├── build.properties │ │ └── plugins.sbt │ │ └── test │ │ └── controllers │ │ └── HomeControllerSpec.scala ├── rails │ ├── Dockerfile │ ├── README.md │ ├── application_controller.rb │ └── routes.rb ├── ruby │ ├── Dockerfile │ ├── Gemfile │ ├── README.md │ └── myapp.rb └── spring-boot │ ├── Dockerfile │ ├── README.md │ ├── pom.xml │ └── src │ └── main │ └── java │ └── example │ └── ExampleApplication.java ├── aws ├── ec2 │ ├── README.md │ ├── app.tf │ ├── main.tf │ ├── outputs.tf │ └── variables.tf ├── ecs │ ├── README.md │ ├── app.tf │ ├── cluster.tf │ ├── main.tf │ └── variables.tf └── eks │ ├── README.md │ ├── app.tf │ ├── cluster.tf │ ├── main.tf │ └── variables.tf ├── ci ├── circleci │ ├── README.md │ └── publish-docker │ │ ├── .circleci │ │ └── config.yml │ │ └── Dockerfile ├── github-actions │ └── publish-docker │ │ ├── .github │ │ └── workflows │ │ │ └── main.yml │ │ └── Dockerfile └── gitlab-ci │ ├── README.md │ ├── deploy-aws │ ├── .gitlab-ci.yml │ ├── deploy.json │ └── deploy.sh │ └── publish-docker │ ├── .gitlab-ci.yml │ └── Dockerfile ├── devops-tools └── terraform │ ├── README.md │ ├── main.tf │ ├── output.tf │ └── variables.tf └── google-cloud ├── gce ├── README.md ├── app.tf ├── main.tf ├── outputs.tf └── variables.tf └── gke ├── README.md ├── app.tf ├── main.tf └── variables.tf /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | **/.terraform 3 | **/*.tfstate 4 | **/*.tfstate.backup 5 | **/terraform.tfvars 6 | -------------------------------------------------------------------------------- /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 |
2 |

3 | 1Password SecretHub has joined 1Password! Find out more on the SecretHub blog. 🎉 4 |

5 |
6 | 7 |

8 | SecretHub 9 |

10 |

11 | Examples 12 |

13 | 14 | [![Discord](https://img.shields.io/badge/chat-on%20discord-7289da.svg?logo=discord)](https://discord.gg/NWmxVeb) 15 | 16 | > [SecretHub][secrethub] is a secrets management tool that works for every engineer. Securely provision passwords and keys throughout your entire stack with just a few lines of code. 17 | 18 | This repository contains code examples for integrations with SecretHub. The README.md for these examples can be found in every directory. For all integrations, take a look at the [integrations page](https://secrethub.io/docs/#integrations). 19 | 20 | We're adding more examples over time (starting with the ones listed below), so keep a lookout for new examples. We'll be adding the ones listed here first. 21 | 22 | If you have a great example of a SecretHub integration yourself or a way to improve an example, feel free (and very welcome) to make a pull request. 23 | 24 | ## Examples 25 | 26 | * CI/CD 27 | * [CircleCI](ci/circleci/) 28 | * [GitHub Actions](ci/github-actions/publish-docker/.github/workflows/main.yml) 29 | * Travis CI 30 | * [GitLab CI](ci/gitlab-ci/) 31 | * Jenkins 32 | * Cloud 33 | * [AWS EC2](aws/ec2) 34 | * [AWS ECS](aws/ecs/) 35 | * AWS Lambda (Golang) 36 | * [Google Compute Engine](google-cloud/gce) 37 | * [Google Kubernetes Engine](google-cloud/gke) 38 | * Linux VMS 39 | * Application 40 | * [Flask](application/flask) 41 | * [Django](application/django) 42 | * [Node.js](application/nodejs) 43 | * [Ruby](application/ruby) 44 | * [Rails](application/rails) 45 | * [Spring Boot](application/spring-boot) 46 | * [ASP.NET](application/aspnet) 47 | * [Kitura](application/kitura) 48 | * [Perfect](application/perfect) 49 | * DevOps tools 50 | * [Terraform](devops-tools/terraform) 51 | * Ansible 52 | * Chef 53 | * Puppet 54 | * IDE 55 | * VS Code 56 | 57 | [secrethub]: https://secrethub.io/ 58 | -------------------------------------------------------------------------------- /application/README.md: -------------------------------------------------------------------------------- 1 | # Example applications 2 | This folder contains the examples for the web application frameworks. The basic structure of all the examples is as followed: 3 | 1. Init the SecretHub demo repository 4 | 2. Create a service account on the demo repository 5 | 3. Build the docker file 6 | 4. Run the docker file 7 | 5. Check if the example works with a curl on localhost:8080. The example returns code 200 if successful and 500 otherwise 8 | ``` 9 | curl -i localhost:8080 10 | ``` 11 | -------------------------------------------------------------------------------- /application/akka/README.md: -------------------------------------------------------------------------------- 1 |

2 | Akka + SecretHub 3 |

4 |
5 | 6 | This Akka example checks if the environment variables `DEMO_USERNAME` and `DEMO_PASSWORD` have been set. If that's the case, you'll receive a `200` on http://localhost:8080 and if it's not, you'll get a `500`. 7 | 8 | ## Prerequisites 9 | 1. [Docker](https://docs.docker.com/install/) installed and running 10 | 1. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 11 | 1. A SecretHub repo that contains a `username` and `password` secret. To create it, run `secrethub demo init`. 12 | 13 | ## Running the example 14 | 15 | Set the SecretHub username in an environment variable 16 | ``` 17 | export SECRETHUB_USERNAME= 18 | ``` 19 | 20 | Create a service account for the demo repo 21 | ``` 22 | secrethub service init --description demo_service \ 23 | --permission read --file demo_service.cred ${SECRETHUB_USERNAME}/demo 24 | ``` 25 | 26 | Build the akka docker demo. You can choose `java` or `scala`, depending on which language you want to see the example in action. 27 | ``` 28 | docker build {java | scala} -t akka-secrethub-demo 29 | ``` 30 | 31 | Run the docker demo with the secrets in the environment variables 32 | ``` 33 | docker run -ti -p 8080:8080 \ 34 | -e DEMO_USERNAME=secrethub://${SECRETHUB_USERNAME}/demo/username \ 35 | -e DEMO_PASSWORD=secrethub://${SECRETHUB_USERNAME}/demo/password \ 36 | -e SECRETHUB_CREDENTIAL=$(cat demo_service.cred) \ 37 | akka-secrethub-demo 38 | ``` 39 | 40 | If you now visit http://localhost:8080, you should see the welcome message including your username. 41 | -------------------------------------------------------------------------------- /application/akka/java/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mozilla/sbt:latest 2 | 3 | # Install SecretHub 4 | RUN curl -sLJO https://deb.secrethub.io/amd64 && \ 5 | dpkg -i secrethub-cli-amd64.deb && \ 6 | rm secrethub-cli-amd64.deb 7 | 8 | COPY example ./example/ 9 | 10 | WORKDIR ./example/ 11 | 12 | # Download project's dependencies 13 | RUN sbt update 14 | 15 | # Add the SecretHub entrypoint 16 | ENTRYPOINT ["secrethub", "run", "--"] 17 | 18 | # Start the main process 19 | CMD ["sbt", "run"] 20 | -------------------------------------------------------------------------------- /application/akka/java/example/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'idea' 3 | apply plugin: 'application' 4 | 5 | repositories { 6 | mavenCentral() 7 | mavenLocal() 8 | } 9 | 10 | def versions = [ 11 | AkkaVersion: "2.6.10", 12 | AkkaHttpVersion: "10.2.2", 13 | ScalaBinary: "2.13" 14 | ] 15 | dependencies { 16 | implementation platform("com.typesafe.akka:akka-http-bom_${versions.ScalaBinary}:${versions.AkkaHttpVersion}") 17 | 18 | implementation "com.typesafe.akka:akka-http_${versions.ScalaBinary}" 19 | implementation "com.typesafe.akka:akka-http-jackson_${versions.ScalaBinary}" 20 | implementation "com.typesafe.akka:akka-actor-typed_${versions.ScalaBinary}:${versions.AkkaVersion}" 21 | implementation "com.typesafe.akka:akka-stream_${versions.ScalaBinary}:${versions.AkkaVersion}" 22 | implementation 'ch.qos.logback:logback-classic:1.2.3' 23 | testImplementation "com.typesafe.akka:akka-http-testkit_${versions.ScalaBinary}" 24 | testImplementation "com.typesafe.akka:akka-actor-testkit-typed_${versions.ScalaBinary}:${versions.AkkaVersion}" 25 | testImplementation 'junit:junit:4.12' 26 | } 27 | 28 | mainClassName = "com.example.QuickstartApp" 29 | 30 | run { 31 | standardInput = System.in 32 | } 33 | -------------------------------------------------------------------------------- /application/akka/java/example/build.sbt: -------------------------------------------------------------------------------- 1 | val akkaHttpVersion = "10.2.2" 2 | val akkaVersion = "2.6.10" 3 | 4 | lazy val root = (project in file(".")). 5 | settings( 6 | inThisBuild(List( 7 | organization := "com.example", 8 | scalaVersion := "2.13.1", 9 | name := "example" 10 | )), 11 | name := "TestProject", 12 | libraryDependencies ++= Seq( 13 | "com.typesafe.akka" %% "akka-http" % akkaHttpVersion, 14 | "com.typesafe.akka" %% "akka-actor-typed" % akkaVersion, 15 | "com.typesafe.akka" %% "akka-stream" % akkaVersion, 16 | "com.typesafe.akka" %% "akka-http-jackson" % akkaHttpVersion, 17 | "ch.qos.logback" % "logback-classic" % "1.2.3", 18 | 19 | "com.typesafe.akka" %% "akka-testkit" % akkaVersion % Test, 20 | "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % Test, 21 | "com.typesafe.akka" %% "akka-actor-testkit-typed" % akkaVersion % Test, 22 | "junit" % "junit" % "4.12" % Test, 23 | "com.novocode" % "junit-interface" % "0.10" % Test 24 | ), 25 | 26 | testOptions += Tests.Argument(TestFrameworks.JUnit, "-v") 27 | ) 28 | -------------------------------------------------------------------------------- /application/akka/java/example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.example 6 | akka-http-seed-java 7 | 1.0 8 | 9 | 10 | 2.6.10 11 | 10.2.2 12 | 2.13 13 | UTF-8 14 | 15 | 16 | 17 | 18 | 19 | com.typesafe.akka 20 | akka-http-bom_${scala.binary.version} 21 | ${akka.http.version} 22 | pom 23 | import 24 | 25 | 26 | 27 | 28 | 29 | 30 | com.typesafe.akka 31 | akka-http_${scala.binary.version} 32 | 33 | 34 | com.typesafe.akka 35 | akka-actor-typed_${scala.binary.version} 36 | ${akka.version} 37 | 38 | 39 | com.typesafe.akka 40 | akka-stream_${scala.binary.version} 41 | ${akka.version} 42 | 43 | 44 | com.typesafe.akka 45 | akka-http-jackson_${scala.binary.version} 46 | 47 | 48 | ch.qos.logback 49 | logback-classic 50 | 1.2.3 51 | 52 | 53 | com.typesafe.akka 54 | akka-http-testkit_${scala.binary.version} 55 | test 56 | 57 | 58 | com.typesafe.akka 59 | akka-actor-testkit-typed_${scala.binary.version} 60 | ${akka.version} 61 | test 62 | 63 | 64 | junit 65 | junit 66 | 4.13.1 67 | test 68 | 69 | 70 | 71 | 72 | 73 | org.apache.maven.plugins 74 | maven-compiler-plugin 75 | 3.5.1 76 | 77 | 11 78 | 11 79 | 80 | 81 | 82 | org.codehaus.mojo 83 | exec-maven-plugin 84 | 1.6.0 85 | 86 | com.example.QuickstartApp 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /application/akka/java/example/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.4.5 2 | -------------------------------------------------------------------------------- /application/akka/java/example/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1") 2 | -------------------------------------------------------------------------------- /application/akka/java/example/src/main/java/com/example/Example.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import akka.NotUsed; 4 | import akka.actor.typed.Behavior; 5 | import akka.http.javadsl.Http; 6 | import akka.http.javadsl.ServerBinding; 7 | import akka.http.javadsl.server.Route; 8 | import akka.actor.typed.javadsl.Behaviors; 9 | import akka.actor.typed.ActorSystem; 10 | import akka.http.javadsl.server.AllDirectives; 11 | 12 | import java.net.InetSocketAddress; 13 | import java.util.concurrent.CompletionStage; 14 | 15 | public class Example extends AllDirectives { 16 | final Route root = path("", () -> get(() -> { 17 | if (System.getenv("DEMO_USERNAME") == null || System.getenv("DEMO_PASSWORD") == null) { 18 | return complete("not all variables are set\n"); 19 | } else { 20 | return complete("Welcome " + System.getenv("DEMO_USERNAME") + "\n"); 21 | } 22 | })); 23 | 24 | static void startHttpServer(Route route, ActorSystem system) { 25 | CompletionStage futureBinding = 26 | Http.get(system).newServerAt("0.0.0.0", 8080).bind(route); 27 | 28 | futureBinding.whenComplete((binding, exception) -> { 29 | if (binding != null) { 30 | InetSocketAddress address = binding.localAddress(); 31 | system.log().info("Server online at http://{}:{}/", 32 | address.getHostString(), 33 | address.getPort()); 34 | } else { 35 | system.log().error("Failed to bind HTTP endpoint, terminating system", exception); 36 | system.terminate(); 37 | } 38 | }); 39 | } 40 | 41 | public static void main(String[] args) { 42 | Behavior rootBehavior = Behaviors.setup(context -> { 43 | startHttpServer(new Example().root, context.getSystem()); 44 | return Behaviors.empty(); 45 | }); 46 | 47 | // boot up server using the route as defined below 48 | ActorSystem.create(rootBehavior, "ExampleAkkaHttpServer"); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /application/akka/java/example/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | my-app { 2 | routes { 3 | # If ask takes more time than this to complete the request is failed 4 | ask-timeout = 5s 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /application/akka/java/example/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | [%date{ISO8601}] [%level] [%logger] [%thread] [%X{akkaSource}] - %msg%n 7 | 8 | 9 | 10 | 11 | 1024 12 | true 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /application/akka/java/example/src/test/resources/application-test.conf: -------------------------------------------------------------------------------- 1 | include "application" 2 | 3 | # default config for tests, we just import the regular conf -------------------------------------------------------------------------------- /application/akka/scala/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mozilla/sbt:latest 2 | 3 | # Install SecretHub 4 | RUN curl -sLJO https://deb.secrethub.io/amd64 && \ 5 | dpkg -i secrethub-cli-amd64.deb && \ 6 | rm secrethub-cli-amd64.deb 7 | 8 | COPY example ./example/ 9 | 10 | WORKDIR ./example/ 11 | 12 | # Download project's dependencies 13 | RUN sbt update 14 | 15 | # Add the SecretHub entrypoint 16 | ENTRYPOINT ["secrethub", "run", "--"] 17 | 18 | # Start the main process 19 | CMD ["sbt", "run"] 20 | -------------------------------------------------------------------------------- /application/akka/scala/example/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | .idea 3 | target/ 4 | -------------------------------------------------------------------------------- /application/akka/scala/example/build.sbt: -------------------------------------------------------------------------------- 1 | lazy val akkaHttpVersion = "10.2.2" 2 | lazy val akkaVersion = "2.6.10" 3 | 4 | lazy val root = (project in file(".")). 5 | settings( 6 | inThisBuild(List( 7 | organization := "com.example", 8 | scalaVersion := "2.13.4" 9 | )), 10 | name := "example", 11 | libraryDependencies ++= Seq( 12 | "com.typesafe.akka" %% "akka-http" % akkaHttpVersion, 13 | "com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion, 14 | "com.typesafe.akka" %% "akka-actor-typed" % akkaVersion, 15 | "com.typesafe.akka" %% "akka-stream" % akkaVersion, 16 | "ch.qos.logback" % "logback-classic" % "1.2.3", 17 | 18 | "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion % Test, 19 | "com.typesafe.akka" %% "akka-actor-testkit-typed" % akkaVersion % Test, 20 | "org.scalatest" %% "scalatest" % "3.1.4" % Test 21 | ) 22 | ) 23 | -------------------------------------------------------------------------------- /application/akka/scala/example/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.4.6 2 | -------------------------------------------------------------------------------- /application/akka/scala/example/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1") 2 | -------------------------------------------------------------------------------- /application/akka/scala/example/src/main/resources/application.conf: -------------------------------------------------------------------------------- 1 | my-app { 2 | routes { 3 | # If ask takes more time than this to complete the request is failed 4 | ask-timeout = 5s 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /application/akka/scala/example/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | [%date{ISO8601}] [%level] [%logger] [%thread] [%X{akkaSource}] - %msg%n 7 | 8 | 9 | 10 | 11 | 1024 12 | true 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /application/akka/scala/example/src/main/scala/com/example/Example.scala: -------------------------------------------------------------------------------- 1 | package com.example 2 | 3 | import akka.actor.typed.ActorSystem 4 | import akka.actor.typed.scaladsl.Behaviors 5 | import akka.http.scaladsl.Http 6 | import akka.http.scaladsl.server.Directives._ 7 | import akka.http.scaladsl.server.Route 8 | 9 | import scala.concurrent.ExecutionContextExecutor 10 | import scala.io.StdIn 11 | import scala.util.Failure 12 | import scala.util.Success 13 | 14 | object Example { 15 | private def startHttpServer(routes: Route)(implicit system: ActorSystem[_]): Unit = { 16 | // Akka HTTP still needs a classic ActorSystem to start 17 | import system.executionContext 18 | 19 | val futureBinding = Http().newServerAt("0.0.0.0", 8080).bind(routes) 20 | futureBinding.onComplete { 21 | case Success(binding) => 22 | val address = binding.localAddress 23 | system.log.info("Server online at http://{}:{}/", address.getHostString, address.getPort) 24 | case Failure(ex) => 25 | system.log.error("Failed to bind HTTP endpoint, terminating system", ex) 26 | system.terminate() 27 | } 28 | } 29 | def main(args: Array[String]): Unit = { 30 | val rootBehavior = Behaviors.setup[Nothing] { context => 31 | val route = 32 | path("") { 33 | get { 34 | if (sys.env.getOrElse("DEMO_USERNAME", "").isEmpty || sys.env.getOrElse("DEMO_PASSWORD", "").isEmpty) { 35 | complete("not all variables are set\n") 36 | } else { 37 | complete("Welcome " + sys.env("DEMO_USERNAME") + "\n") 38 | } 39 | } 40 | } 41 | startHttpServer(route)(context.system) 42 | 43 | Behaviors.empty 44 | } 45 | val system = ActorSystem[Nothing](rootBehavior, "HelloAkkaHttpServer") 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /application/akka/scala/example/src/test/resources/application-test.conf: -------------------------------------------------------------------------------- 1 | include "application" 2 | 3 | # default config for tests, we just import the regular conf 4 | -------------------------------------------------------------------------------- /application/aspnet/cli-example/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build app 2 | FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build 3 | WORKDIR /source 4 | 5 | # copy csproj and restore as distinct layers 6 | COPY *.sln . 7 | COPY example/*.csproj ./example/ 8 | RUN dotnet restore -r linux-musl-x64 9 | 10 | # copy everything else and build app 11 | COPY example/. ./example/ 12 | WORKDIR /source/example 13 | RUN dotnet publish -c release -o /app -r linux-musl-x64 --self-contained false --no-restore 14 | 15 | # Run app 16 | FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine 17 | WORKDIR /app 18 | COPY --from=build /app ./ 19 | 20 | # Install SecretHub 21 | RUN apk add --repository https://alpine.secrethub.io/alpine/edge/main --allow-untrusted secrethub-cli 22 | 23 | # Expose aspnet standard port 80 24 | EXPOSE 80 25 | 26 | # Add the SecretHub entrypoint 27 | ENTRYPOINT ["secrethub", "run", "--"] 28 | 29 | CMD ["./example"] 30 | -------------------------------------------------------------------------------- /application/aspnet/cli-example/README.md: -------------------------------------------------------------------------------- 1 |

2 | ASP.NET + SecretHub 3 |

4 |
5 | 6 | This ASP.NET example checks if the environment variables `DEMO_USERNAME` and `DEMO_PASSWORD` have been set. If that's the case, you'll receive a `200` on http://localhost:8080 and if it's not, you'll get a `500`. 7 | 8 | ## Prerequisites 9 | 1. [Docker](https://docs.docker.com/install/) installed and running 10 | 1. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 11 | 1. A SecretHub repo that contains a `username` and `password` secret. To create it, run `secrethub demo init`. 12 | 13 | ## Running the example 14 | 15 | Set the SecretHub username in an environment variable 16 | ``` 17 | export SECRETHUB_USERNAME= 18 | ``` 19 | 20 | Create a service account for the demo repo 21 | ``` 22 | secrethub service init --description demo_service \ 23 | --permission read --file demo_service.cred ${SECRETHUB_USERNAME}/demo 24 | ``` 25 | 26 | Build the ASP.NET docker demo 27 | ``` 28 | docker build . -t aspnet-secrethub-demo 29 | ``` 30 | 31 | Run the docker demo with the secrets in the environment variables 32 | ``` 33 | docker run -p 8080:80 \ 34 | -e DEMO_USERNAME=secrethub://${SECRETHUB_USERNAME}/demo/username \ 35 | -e DEMO_PASSWORD=secrethub://${SECRETHUB_USERNAME}/demo/password \ 36 | -e SECRETHUB_CREDENTIAL=$(cat demo_service.cred) \ 37 | aspnet-secrethub-demo 38 | ``` 39 | 40 | If you now visit http://localhost:8080, you should see the welcome message including your username. 41 | -------------------------------------------------------------------------------- /application/aspnet/cli-example/aspnetapp.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 15 3 | VisualStudioVersion = 15.0.27130.2027 4 | MinimumVisualStudioVersion = 15.0.26124.0 5 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "example", "example\example.csproj", "{5FDCC1ED-9F59-47ED-969D-5E463CDD8D52}" 6 | EndProject 7 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1E1C7ABA-885A-4273-811E-B66AD28F9A87}" 8 | ProjectSection(SolutionItems) = preProject 9 | Directory.Build.props = Directory.Build.props 10 | Dockerfile = Dockerfile 11 | Dockerfile.alpine-x64 = Dockerfile.alpine-x64 12 | EndProjectSection 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Debug|x64 = Debug|x64 18 | Debug|x86 = Debug|x86 19 | Release|Any CPU = Release|Any CPU 20 | Release|x64 = Release|x64 21 | Release|x86 = Release|x86 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {5FDCC1ED-9F59-47ED-969D-5E463CDD8D52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {5FDCC1ED-9F59-47ED-969D-5E463CDD8D52}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {5FDCC1ED-9F59-47ED-969D-5E463CDD8D52}.Debug|x64.ActiveCfg = Debug|Any CPU 27 | {5FDCC1ED-9F59-47ED-969D-5E463CDD8D52}.Debug|x64.Build.0 = Debug|Any CPU 28 | {5FDCC1ED-9F59-47ED-969D-5E463CDD8D52}.Debug|x86.ActiveCfg = Debug|Any CPU 29 | {5FDCC1ED-9F59-47ED-969D-5E463CDD8D52}.Debug|x86.Build.0 = Debug|Any CPU 30 | {5FDCC1ED-9F59-47ED-969D-5E463CDD8D52}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {5FDCC1ED-9F59-47ED-969D-5E463CDD8D52}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {5FDCC1ED-9F59-47ED-969D-5E463CDD8D52}.Release|x64.ActiveCfg = Release|Any CPU 33 | {5FDCC1ED-9F59-47ED-969D-5E463CDD8D52}.Release|x64.Build.0 = Release|Any CPU 34 | {5FDCC1ED-9F59-47ED-969D-5E463CDD8D52}.Release|x86.ActiveCfg = Release|Any CPU 35 | {5FDCC1ED-9F59-47ED-969D-5E463CDD8D52}.Release|x86.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {C9A7C5A2-5C90-4AD9-ABB8-6F2D2364D5AF} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /application/aspnet/cli-example/example/Pages/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model IndexModel 3 | 4 | @Model.Content() 5 | -------------------------------------------------------------------------------- /application/aspnet/cli-example/example/Pages/Index.cshtml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Mvc.RazorPages; 3 | using Microsoft.Extensions.Logging; 4 | using System; 5 | 6 | namespace example.Pages 7 | { 8 | public class IndexModel : PageModel 9 | { 10 | public string Content() 11 | { 12 | string content; 13 | string username = Environment.GetEnvironmentVariable("DEMO_USERNAME"); 14 | string password = Environment.GetEnvironmentVariable("DEMO_PASSWORD"); 15 | 16 | if( (string.IsNullOrEmpty(username)) || (string.IsNullOrEmpty(username)) ){ 17 | Response.StatusCode = 500; 18 | content = "not all variables are set"; 19 | } 20 | else{ 21 | Response.StatusCode = 200; 22 | content = "Welcome " + username; 23 | } 24 | return content; 25 | } 26 | 27 | public void OnGet() 28 | { 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /application/aspnet/cli-example/example/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using example 2 | @namespace example.Pages 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /application/aspnet/cli-example/example/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace example 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /application/aspnet/cli-example/example/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:53930", 7 | "sslPort": 44370 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "aspnetapp": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | }, 26 | "publicdev": { 27 | "commandName": "Project", 28 | "launchBrowser": true, 29 | "applicationUrl": "http://+:80", 30 | "environmentVariables": { 31 | "ASPNETCORE_ENVIRONMENT": "Development" 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /application/aspnet/cli-example/example/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.AspNetCore.HttpsPolicy; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Hosting; 11 | 12 | namespace example 13 | { 14 | public class Startup 15 | { 16 | public Startup(IConfiguration configuration) 17 | { 18 | Configuration = configuration; 19 | } 20 | 21 | public IConfiguration Configuration { get; } 22 | 23 | // This method gets called by the runtime. Use this method to add services to the container. 24 | public void ConfigureServices(IServiceCollection services) 25 | { 26 | services.AddRazorPages(); 27 | } 28 | 29 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 30 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 31 | { 32 | if (env.IsDevelopment()) 33 | { 34 | app.UseDeveloperExceptionPage(); 35 | } 36 | else 37 | { 38 | app.UseExceptionHandler("/Error"); 39 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 40 | app.UseHsts(); 41 | } 42 | 43 | app.UseHttpsRedirection(); 44 | app.UseStatusCodePages(); 45 | app.UseStaticFiles(); 46 | 47 | app.UseRouting(); 48 | 49 | app.UseAuthorization(); 50 | 51 | app.UseEndpoints(endpoints => 52 | { 53 | endpoints.MapRazorPages(); 54 | }); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /application/aspnet/cli-example/example/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /application/aspnet/cli-example/example/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /application/aspnet/cli-example/example/example.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /application/aspnet/sdk-example/Dockerfile: -------------------------------------------------------------------------------- 1 | # .NET CORE 3.1 base image 2 | FROM mcr.microsoft.com/dotnet/core/sdk:3.1 3 | 4 | # Create new app 5 | RUN dotnet new webApp -o example --no-https 6 | 7 | # Add modified files 8 | COPY ./example ./example 9 | 10 | # Change workdir so the run command will be run in project 11 | WORKDIR /example 12 | 13 | # Default port 14 | EXPOSE 5000 15 | 16 | # Run command, set to receive requests from everywhere (0.0.0.0) on default 17 | CMD ["dotnet", "run", "--urls", "http://0.0.0.0:5000"] 18 | -------------------------------------------------------------------------------- /application/aspnet/sdk-example/README.md: -------------------------------------------------------------------------------- 1 |

2 | ASP.NET + SecretHub 3 |

4 |
5 | 6 | This example demonstrates the use of the [.NET SDK](https://github.com/secrethub/secrethub-dotnet) in an ASP.NET application. 7 | Following the steps below will result in an welcome message on http://localhost:5000. 8 | If any error occurs, you will receive a descriptive error message in the console. 9 | 10 | ## Prerequisites 11 | 1. [Docker](https://docs.docker.com/install/) installed and running 12 | 1. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 13 | 1. A SecretHub repo that contains a `username` and `password` secret. To create it, run `secrethub demo init`. 14 | 15 | ## Running the example 16 | 17 | Set the SecretHub username in an environment variable. 18 | ``` 19 | export SECRETHUB_USERNAME= 20 | ``` 21 | 22 | Create a service account for the demo repo. 23 | ``` 24 | secrethub service init --description demo_service \ 25 | --permission read --file demo_service.cred ${SECRETHUB_USERNAME}/demo 26 | ``` 27 | 28 | Build the ASP.NET docker demo. 29 | ``` 30 | docker build . -t aspnet-secrethub-demo 31 | ``` 32 | 33 | Run the docker demo, passing the newly created service credential and the paths in the secret store as environment variables. 34 | ``` 35 | docker run -e SECRETHUB_CREDENTIAL=$(cat demo_service.cred) \ 36 | -e DEMO_USERNAME=secrethub://${SECRETHUB_USERNAME}/demo/username \ 37 | -e DEMO_PASSWORD=secrethub://${SECRETHUB_USERNAME}/demo/password \ 38 | -p 5000:5000 aspnet-secrethub-demo 39 | ``` 40 | 41 | If you now visit http://localhost:5000, you should see the welcome message including your username. 42 | -------------------------------------------------------------------------------- /application/aspnet/sdk-example/example/Pages/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page 2 | @model IndexModel 3 | @{ 4 | ViewData["Title"] = "Home page"; 5 | } 6 | 7 |
8 |

@Model.Message

9 |
10 | -------------------------------------------------------------------------------- /application/aspnet/sdk-example/example/Pages/Index.cshtml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Microsoft.AspNetCore.Mvc.RazorPages; 7 | using Microsoft.Extensions.Logging; 8 | namespace example.Pages 9 | { 10 | public class IndexModel : PageModel 11 | { 12 | private readonly ILogger _logger; 13 | public string Message { get; set; } 14 | public IndexModel(ILogger logger) 15 | { 16 | _logger = logger; 17 | } 18 | public void OnGet() 19 | { 20 | Message = response(); 21 | } 22 | public static string response() 23 | { 24 | try 25 | { 26 | var secrets = new SecretHub.Client().ResolveEnv(); 27 | string username = secrets["DEMO_USERNAME"]; 28 | string password = secrets["DEMO_PASSWORD"]; 29 | return "Hello, " + username + "!"; 30 | } 31 | catch (Exception e) 32 | { 33 | Console.WriteLine(e); 34 | return "Your username, password or SecretHub credential have not been set correctly."; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /application/aspnet/sdk-example/example/example.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /application/django/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.7-alpine 2 | ENV PYTHONUNBUFFERED 1 3 | RUN mkdir /code 4 | WORKDIR /code 5 | COPY requirements.txt /code/ 6 | 7 | # Install essentials for Django 8 | RUN apk add --no-cache --virtual .build-deps \ 9 | ca-certificates gcc postgresql-dev linux-headers musl-dev \ 10 | libffi-dev jpeg-dev zlib-dev \ 11 | && pip install -r requirements.txt 12 | 13 | # Install SecretHub 14 | RUN apk add --repository https://alpine.secrethub.io/alpine/edge/main --allow-untrusted secrethub-cli 15 | 16 | # Let django-admin set up the framework 17 | RUN django-admin startproject project . 18 | 19 | # Copy example code 20 | COPY urls.py /code/project/urls.py 21 | COPY views.py views.py 22 | 23 | # Expose django standard port 8000 24 | EXPOSE 8000 25 | 26 | # Add the SecretHub entrypoint 27 | ENTRYPOINT ["secrethub", "run", "--"] 28 | 29 | # Start the main process 30 | CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] 31 | -------------------------------------------------------------------------------- /application/django/README.md: -------------------------------------------------------------------------------- 1 |

2 | Django + SecretHub 3 |

4 |
5 | 6 |

7 | View Docs 8 |

9 |
10 | 11 | This Django example checks if the environment variables `DEMO_USERNAME` and `DEMO_PASSWORD` have been set. If that's the case, you'll receive a `200` on http://localhost:8080 and if it's not, you'll get a `500`. 12 | 13 | ## Prerequisites 14 | 1. [Docker](https://docs.docker.com/install/) installed and running 15 | 1. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 16 | 1. A SecretHub repo that contains a `username` and `password` secret. To create it, run `secrethub demo init`. 17 | 18 | ## Running the example 19 | 20 | Set the SecretHub username in an environment variable 21 | ``` 22 | export SECRETHUB_USERNAME= 23 | ``` 24 | 25 | Create a service account for the demo repo 26 | ``` 27 | secrethub service init --description demo_service \ 28 | --permission read --file demo_service.cred ${SECRETHUB_USERNAME}/demo 29 | ``` 30 | 31 | Build the django docker demo 32 | ``` 33 | docker build . -t django-secrethub-demo 34 | ``` 35 | 36 | Run the docker demo with the secrets in the environment variables 37 | ``` 38 | docker run -p 8080:8000 \ 39 | -e DEMO_USERNAME=secrethub://${SECRETHUB_USERNAME}/demo/username \ 40 | -e DEMO_PASSWORD=secrethub://${SECRETHUB_USERNAME}/demo/password \ 41 | -e SECRETHUB_CREDENTIAL=$(cat demo_service.cred) \ 42 | django-secrethub-demo 43 | ``` 44 | 45 | If you now visit http://localhost:8080, you should see the welcome message including your username. 46 | -------------------------------------------------------------------------------- /application/django/requirements.txt: -------------------------------------------------------------------------------- 1 | Django>=3.0 2 | psycopg2>=2.7 3 | -------------------------------------------------------------------------------- /application/django/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import include, path 3 | from views import index 4 | 5 | urlpatterns = [ 6 | path('', index, name='index'), 7 | ] 8 | -------------------------------------------------------------------------------- /application/django/views.py: -------------------------------------------------------------------------------- 1 | from django.http import HttpResponse 2 | from os import getenv 3 | 4 | def index(request): 5 | if not (getenv('DEMO_USERNAME') and getenv('DEMO_PASSWORD')): 6 | content = 'not all variables are set' 7 | status = 500 8 | else: 9 | content = 'Welcome ' + str(getenv('DEMO_USERNAME')) 10 | status = 200 11 | return HttpResponse(content,status=status) 12 | -------------------------------------------------------------------------------- /application/flask/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.7-alpine 2 | COPY . /app 3 | WORKDIR /app 4 | RUN pip install -r requirements.txt 5 | 6 | # Install SecretHub 7 | RUN apk add --repository https://alpine.secrethub.io/alpine/edge/main --allow-untrusted secrethub-cli 8 | 9 | # Expose flask standard port 5000 10 | EXPOSE 5000 11 | 12 | # # Add the SecretHub entrypoint 13 | ENTRYPOINT ["secrethub", "run", "--"] 14 | 15 | # Start the main process 16 | CMD ["python", "app.py"] 17 | -------------------------------------------------------------------------------- /application/flask/README.md: -------------------------------------------------------------------------------- 1 |

2 | Flask + SecretHub 3 |

4 |
5 | 6 | This Flask example checks if the environment variables `DEMO_USERNAME` and `DEMO_PASSWORD` have been set. If that's the case, you'll receive a `200` on http://localhost:8080 and if it's not, you'll get a `500`. 7 | 8 | ## Prerequisites 9 | 1. [Docker](https://docs.docker.com/install/) installed and running 10 | 1. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 11 | 1. A SecretHub repo that contains a `username` and `password` secret. To create it, run `secrethub demo init`. 12 | 13 | ## Running the example 14 | 15 | Set the SecretHub username in an environment variable 16 | ``` 17 | export SECRETHUB_USERNAME= 18 | ``` 19 | 20 | Create a service account for the demo repo 21 | ``` 22 | secrethub service init --description demo_service \ 23 | --permission read --file demo_service.cred ${SECRETHUB_USERNAME}/demo 24 | ``` 25 | 26 | Build the flask docker demo 27 | ``` 28 | docker build . -t flask-secrethub-demo 29 | ``` 30 | 31 | Run the docker demo with the secrets in the environment variables 32 | ``` 33 | docker run -ti -p 8080:5000 \ 34 | -e DEMO_USERNAME=secrethub://${SECRETHUB_USERNAME}/demo/username \ 35 | -e DEMO_PASSWORD=secrethub://${SECRETHUB_USERNAME}/demo/password \ 36 | -e SECRETHUB_CREDENTIAL=$(cat demo_service.cred) \ 37 | flask-secrethub-demo 38 | ``` 39 | 40 | If you now visit http://localhost:8080, you should see the welcome message including your username. 41 | -------------------------------------------------------------------------------- /application/flask/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask_restful import Resource, Api 3 | from os import getenv 4 | 5 | app = Flask(__name__) 6 | api = Api(app) 7 | 8 | class Example(Resource): 9 | def get(self): 10 | if not (getenv('DEMO_USERNAME') and getenv('DEMO_PASSWORD')): 11 | content = 'not all variables are set' 12 | status = 500 13 | else: 14 | content = 'Welcome ' + str(getenv('DEMO_USERNAME')) 15 | status = 200 16 | return content,status 17 | 18 | api.add_resource(Example, '/') 19 | 20 | if __name__ == '__main__': 21 | app.run(debug=True, host='0.0.0.0') 22 | -------------------------------------------------------------------------------- /application/flask/requirements.txt: -------------------------------------------------------------------------------- 1 | flask==1.1.1 2 | flask_restful==0.3.8 3 | -------------------------------------------------------------------------------- /application/kitura/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ibmcom/kitura-ubuntu:latest 2 | 3 | # Define a working directory 4 | RUN mkdir HelloKitura 5 | WORKDIR ./HelloKitura 6 | 7 | # Install SecretHub 8 | RUN echo "deb [trusted=yes] https://apt.secrethub.io stable main" > /etc/apt/sources.list.d/secrethub.sources.list && apt-get update 9 | RUN apt-get install -y secrethub-cli 10 | 11 | # Initialize the application as an executable 12 | RUN swift package init --type executable 13 | 14 | # Copy the necessary files 15 | COPY ./HelloKitura /HelloKitura 16 | 17 | # Get the dependencies 18 | RUN swift build 19 | 20 | # Expose the default port 21 | EXPOSE 8080 22 | 23 | # Wrap the command with 'secrethub run' 24 | ENTRYPOINT [ "secrethub", "run", "--" ] 25 | 26 | # Run the application 27 | CMD [ "swift", "run" ] 28 | -------------------------------------------------------------------------------- /application/kitura/HelloKitura/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "HelloKitura", 6 | dependencies: [ 7 | .package(url: "https://github.com/IBM-Swift/Kitura", from: "2.8.0") 8 | ], 9 | targets: [ 10 | .target( 11 | name: "HelloKitura", 12 | dependencies: ["Kitura"]), 13 | .testTarget( 14 | name: "HelloKituraTests", 15 | dependencies: ["HelloKitura"]), 16 | ] 17 | ) 18 | -------------------------------------------------------------------------------- /application/kitura/HelloKitura/Sources/HelloKitura/main.swift: -------------------------------------------------------------------------------- 1 | import Kitura 2 | import Foundation 3 | 4 | let router = Router() 5 | 6 | if ProcessInfo.processInfo.environment["DEMO_USERNAME"] == nil || ProcessInfo.processInfo.environment["DEMO_PASSWORD"] == nil { 7 | router.get("/") { request, response, next in 8 | response.send("either the DEMO_USERNAME environment variable, DEMO_PASSWORD environment variable, or both have not been set.") 9 | next() 10 | } 11 | } 12 | else { 13 | router.get("/") { request, response, next in 14 | response.send("welcome, \(ProcessInfo.processInfo.environment["DEMO_USERNAME"] ?? "")") 15 | } 16 | } 17 | 18 | Kitura.addHTTPServer(onPort: 8080, with: router) 19 | Kitura.run() 20 | -------------------------------------------------------------------------------- /application/kitura/README.md: -------------------------------------------------------------------------------- 1 | This Kitura example checks if the environment variables DEMO_USERNAME and DEMO_PASSWORD have been set. If that's the not case, you'll receive an error message at http://localhost:8080. 2 | 3 | ## Prerequisites 4 | 1. [Docker](https://docs.docker.com/install/) installed and running 5 | 1. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 6 | 1. A SecretHub repo that contains a `username` and `password` secret. To create it, run `secrethub demo init`. 7 | 8 | ## Running the example 9 | 10 | Set the SecretHub username in an environment variable 11 | ``` 12 | export SECRETHUB_USERNAME= 13 | ``` 14 | 15 | Create a service account for the demo repo 16 | ``` 17 | secrethub service init --description demo_service \ 18 | --permission read --file demo_service.cred ${SECRETHUB_USERNAME}/demo 19 | ``` 20 | 21 | Build the Kitura docker demo 22 | ``` 23 | docker build . -t kitura-secrethub-demo 24 | ``` 25 | 26 | Run the docker demo with the secrets in the environment variables 27 | ``` 28 | docker run -p 8080:8080 \ 29 | -e DEMO_USERNAME=secrethub://${SECRETHUB_USERNAME}/demo/username \ 30 | -e DEMO_PASSWORD=secrethub://${SECRETHUB_USERNAME}/demo/password \ 31 | -e SECRETHUB_CREDENTIAL=$(cat demo_service.cred) \ 32 | kitura-secrethub-demo 33 | ``` 34 | 35 | If you now visit http://localhost:8080, you should see the welcome message including your username. 36 | -------------------------------------------------------------------------------- /application/nodejs/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:13.13-alpine 2 | WORKDIR /app 3 | COPY package*.json /app/ 4 | RUN npm install 5 | COPY . /app 6 | 7 | # Install SecretHub 8 | RUN apk add --repository https://alpine.secrethub.io/alpine/edge/main --allow-untrusted secrethub-cli 9 | 10 | # Expose http-server standard port 11 | EXPOSE 8080 12 | 13 | # Add the SecretHub entrypoint 14 | ENTRYPOINT ["secrethub", "run", "--"] 15 | 16 | # Start the main process 17 | CMD ["npm", "start"] 18 | -------------------------------------------------------------------------------- /application/nodejs/README.md: -------------------------------------------------------------------------------- 1 |

2 | Node.js + SecretHub 3 |

4 |
5 | 6 |

7 | View Docs 8 |

9 |
10 | 11 | This Node.js example checks if the environment variables `DEMO_USERNAME` and `DEMO_PASSWORD` have been set. If that's the case, you'll receive a `200` on http://localhost:8080 and if it's not, you'll get a `500`. 12 | 13 | ## Prerequisites 14 | 1. [Docker](https://docs.docker.com/install/) installed and running 15 | 1. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 16 | 1. A SecretHub repo that contains a `username` and `password` secret. To create it, run `secrethub demo init`. 17 | 18 | ## Running the example 19 | 20 | Set the SecretHub username in an environment variable 21 | ``` 22 | export SECRETHUB_USERNAME= 23 | ``` 24 | 25 | Create a service account for the demo repo 26 | ``` 27 | secrethub service init --description demo_service \ 28 | --permission read --file demo_service.cred ${SECRETHUB_USERNAME}/demo 29 | ``` 30 | 31 | Build the Node.js docker demo 32 | ``` 33 | docker build . -t nodejs-secrethub-demo 34 | ``` 35 | 36 | Run the docker demo with the secrets in the environment variables 37 | ``` 38 | docker run -p 8080:8080 \ 39 | -e DEMO_USERNAME=secrethub://${SECRETHUB_USERNAME}/demo/username \ 40 | -e DEMO_PASSWORD=secrethub://${SECRETHUB_USERNAME}/demo/password \ 41 | -e SECRETHUB_CREDENTIAL=$(cat demo_service.cred) \ 42 | nodejs-secrethub-demo 43 | ``` 44 | 45 | If you now visit http://localhost:8080, you should see the welcome message including your username. 46 | -------------------------------------------------------------------------------- /application/nodejs/index.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | 3 | http.createServer(function (req, res) { 4 | if((process.env.DEMO_USERNAME) && (process.env.DEMO_PASSWORD)){ 5 | res.writeHead(200, {'Content-Type': 'text/plain'}); 6 | res.end('Welcome ' + process.env.DEMO_USERNAME); 7 | } 8 | else{ 9 | res.writeHead(500, {'Content-Type': 'text/plain'}); 10 | res.end('not all variables are set'); 11 | } 12 | }).listen(8080); 13 | -------------------------------------------------------------------------------- /application/nodejs/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-secrethub-demo", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "async": { 8 | "version": "2.6.4", 9 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", 10 | "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", 11 | "requires": { 12 | "lodash": "^4.17.14" 13 | } 14 | }, 15 | "basic-auth": { 16 | "version": "1.1.0", 17 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", 18 | "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=" 19 | }, 20 | "call-bind": { 21 | "version": "1.0.2", 22 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 23 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 24 | "requires": { 25 | "function-bind": "^1.1.1", 26 | "get-intrinsic": "^1.0.2" 27 | } 28 | }, 29 | "colors": { 30 | "version": "1.4.0", 31 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", 32 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" 33 | }, 34 | "corser": { 35 | "version": "2.0.1", 36 | "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", 37 | "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=" 38 | }, 39 | "debug": { 40 | "version": "3.2.6", 41 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 42 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 43 | "requires": { 44 | "ms": "^2.1.1" 45 | } 46 | }, 47 | "eventemitter3": { 48 | "version": "4.0.0", 49 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", 50 | "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==" 51 | }, 52 | "follow-redirects": { 53 | "version": "1.14.8", 54 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", 55 | "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" 56 | }, 57 | "function-bind": { 58 | "version": "1.1.1", 59 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 60 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 61 | }, 62 | "get-intrinsic": { 63 | "version": "1.1.3", 64 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", 65 | "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", 66 | "requires": { 67 | "function-bind": "^1.1.1", 68 | "has": "^1.0.3", 69 | "has-symbols": "^1.0.3" 70 | } 71 | }, 72 | "has": { 73 | "version": "1.0.3", 74 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 75 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 76 | "requires": { 77 | "function-bind": "^1.1.1" 78 | } 79 | }, 80 | "has-symbols": { 81 | "version": "1.0.3", 82 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 83 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 84 | }, 85 | "he": { 86 | "version": "1.2.0", 87 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 88 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" 89 | }, 90 | "http-proxy": { 91 | "version": "1.18.1", 92 | "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", 93 | "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", 94 | "requires": { 95 | "eventemitter3": "^4.0.0", 96 | "follow-redirects": "^1.0.0", 97 | "requires-port": "^1.0.0" 98 | } 99 | }, 100 | "http-server": { 101 | "version": "0.12.1", 102 | "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.1.tgz", 103 | "integrity": "sha512-T0jB+7J7GJ2Vo+a4/T7P7SbQ3x2GPDnqRqQXdfEuPuUOmES/9NBxPnDm7dh1HGEeUWqUmLUNtGV63ZC5Uy3tGA==", 104 | "requires": { 105 | "basic-auth": "^1.0.3", 106 | "colors": "^1.3.3", 107 | "corser": "^2.0.1", 108 | "ecstatic": "^3.3.2", 109 | "http-proxy": "^1.17.0", 110 | "opener": "^1.5.1", 111 | "optimist": "~0.6.1", 112 | "portfinder": "^1.0.20", 113 | "secure-compare": "3.0.1", 114 | "union": "~0.5.0" 115 | }, 116 | "dependencies": { 117 | "ecstatic": { 118 | "version": "3.3.2", 119 | "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", 120 | "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", 121 | "requires": { 122 | "he": "^1.1.1", 123 | "mime": "^1.6.0", 124 | "minimist": "^1.1.0", 125 | "url-join": "^2.0.5" 126 | } 127 | } 128 | } 129 | }, 130 | "lodash": { 131 | "version": "4.17.21", 132 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 133 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 134 | }, 135 | "mime": { 136 | "version": "1.6.0", 137 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 138 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 139 | }, 140 | "minimist": { 141 | "version": "1.2.5", 142 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 143 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 144 | }, 145 | "mkdirp": { 146 | "version": "0.5.5", 147 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 148 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 149 | "requires": { 150 | "minimist": "^1.2.5" 151 | } 152 | }, 153 | "ms": { 154 | "version": "2.1.2", 155 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 156 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 157 | }, 158 | "object-inspect": { 159 | "version": "1.12.2", 160 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", 161 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" 162 | }, 163 | "opener": { 164 | "version": "1.5.1", 165 | "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.1.tgz", 166 | "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==" 167 | }, 168 | "optimist": { 169 | "version": "0.6.1", 170 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", 171 | "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", 172 | "requires": { 173 | "minimist": "~0.0.1", 174 | "wordwrap": "~0.0.2" 175 | }, 176 | "dependencies": { 177 | "minimist": { 178 | "version": "0.0.10", 179 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", 180 | "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" 181 | } 182 | } 183 | }, 184 | "portfinder": { 185 | "version": "1.0.25", 186 | "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz", 187 | "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==", 188 | "requires": { 189 | "async": "^2.6.2", 190 | "debug": "^3.1.1", 191 | "mkdirp": "^0.5.1" 192 | } 193 | }, 194 | "qs": { 195 | "version": "6.11.0", 196 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 197 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 198 | "requires": { 199 | "side-channel": "^1.0.4" 200 | } 201 | }, 202 | "requires-port": { 203 | "version": "1.0.0", 204 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 205 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" 206 | }, 207 | "secure-compare": { 208 | "version": "3.0.1", 209 | "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", 210 | "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=" 211 | }, 212 | "side-channel": { 213 | "version": "1.0.4", 214 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 215 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 216 | "requires": { 217 | "call-bind": "^1.0.0", 218 | "get-intrinsic": "^1.0.2", 219 | "object-inspect": "^1.9.0" 220 | } 221 | }, 222 | "union": { 223 | "version": "0.5.0", 224 | "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", 225 | "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", 226 | "requires": { 227 | "qs": "^6.4.0" 228 | } 229 | }, 230 | "url-join": { 231 | "version": "2.0.5", 232 | "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", 233 | "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=" 234 | }, 235 | "wordwrap": { 236 | "version": "0.0.3", 237 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 238 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" 239 | } 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /application/nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-secrethub-demo", 3 | "version": "1.0.0", 4 | "description": "nodejs-secrethub-demo", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "author": "SecretHub", 10 | "license": "MIT", 11 | "private": true, 12 | "dependencies": { 13 | "http-server": "^0.12.1" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /application/perfect/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM swift:5.2.5 2 | 3 | RUN apt-get update 4 | 5 | RUN apt-get install -y openssl libssl-dev uuid-dev 6 | 7 | RUN echo "deb [trusted=yes] https://apt.secrethub.io stable main" > /etc/apt/sources.list.d/secrethub.sources.list && apt-get update 8 | RUN apt-get install -y secrethub-cli 9 | 10 | RUN git clone https://github.com/PerfectlySoft/PerfectTemplate.git 11 | 12 | COPY ./PerfectTemplate /PerfectTemplate 13 | WORKDIR ./PerfectTemplate 14 | RUN swift build 15 | 16 | EXPOSE 8181 17 | ENTRYPOINT [ "secrethub", "run", "--"] 18 | CMD ["/PerfectTemplate/.build/debug/PerfectTemplate"] 19 | -------------------------------------------------------------------------------- /application/perfect/PerfectTemplate/Sources/PerfectTemplate/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // PerfectTemplate 4 | // 5 | // Created by Kyle Jessup on 2015-11-05. 6 | // Copyright (C) 2015 PerfectlySoft, Inc. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This source file is part of the Perfect.org open source project 11 | // 12 | // Copyright (c) 2015 - 2016 PerfectlySoft Inc. and the Perfect project authors 13 | // Licensed under Apache License v2.0 14 | // 15 | // See http://perfect.org/licensing.html for license information 16 | // 17 | //===----------------------------------------------------------------------===// 18 | // 19 | 20 | import PerfectHTTP 21 | import PerfectHTTPServer 22 | import Foundation 23 | 24 | 25 | func giveResponse() -> String { 26 | if ProcessInfo.processInfo.environment["DEMO_USERNAME"] == nil || ProcessInfo.processInfo.environment["DEMO_PASSWORD"] == nil { 27 | return "either the DEMO_USERNAME environment variable, DEMO_PASSWORD environment variable, or both have not been set." 28 | } 29 | else { 30 | return "welcome, \(ProcessInfo.processInfo.environment["DEMO_USERNAME"] ?? "")" 31 | } 32 | } 33 | // An example request handler. 34 | // This 'handler' function can be referenced directly in the configuration below. 35 | func handler(request: HTTPRequest, response: HTTPResponse) { 36 | // Respond with a simple message. 37 | response.setHeader(.contentType, value: "text/html") 38 | response.appendBody(string: "Hello, world!\(giveResponse())") 39 | // Ensure that response.completed() is called when your processing is done. 40 | response.completed() 41 | } 42 | 43 | // Configure one server which: 44 | // * Serves the hello world message at :/ 45 | // * Serves static files out of the "./webroot" 46 | // directory (which must be located in the current working directory). 47 | // * Performs content compression on outgoing data when appropriate. 48 | var routes = Routes() 49 | routes.add(method: .get, uri: "/", handler: handler) 50 | routes.add(method: .get, uri: "/**", 51 | handler: StaticFileHandler(documentRoot: "./webroot", allowResponseFilters: true).handleRequest) 52 | try HTTPServer.launch(name: "localhost", 53 | port: 8181, 54 | routes: routes, 55 | responseFilters: [ 56 | (PerfectHTTPServer.HTTPFilter.contentCompression(data: [:]), HTTPFilterPriority.high)]) 57 | -------------------------------------------------------------------------------- /application/perfect/README.md: -------------------------------------------------------------------------------- 1 | This Perfect example checks if the environment variables `DEMO_USERNAME` and `DEMO_PASSWORD` have been set. If that's not the case, you'll receive an error message on http://localhost:8181. 2 | 3 | ## Prerequisites 4 | 1. [Docker](https://docs.docker.com/install/) installed and running 5 | 1. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 6 | 1. A SecretHub repo that contains a `username` and `password` secret. To create it, run `secrethub demo init`. 7 | 8 | ## Running the example 9 | 10 | Set the SecretHub username in an environment variable 11 | ``` 12 | export SECRETHUB_USERNAME= 13 | ``` 14 | 15 | Create a service account for the demo repo 16 | ``` 17 | secrethub service init --description demo_service \ 18 | --permission read --file demo_service.cred ${SECRETHUB_USERNAME}/demo 19 | ``` 20 | 21 | Build the Perfect docker demo 22 | ``` 23 | docker build . -t perfect-secrethub-demo 24 | ``` 25 | 26 | Run the docker demo with the secrets in the environment variables 27 | ``` 28 | docker run -p 8181:8181 \ 29 | -e DEMO_USERNAME=secrethub://${SECRETHUB_USERNAME}/demo/username \ 30 | -e DEMO_PASSWORD=secrethub://${SECRETHUB_USERNAME}/demo/password \ 31 | -e SECRETHUB_CREDENTIAL=$(cat demo_service.cred) \ 32 | perfect-secrethub-demo 33 | ``` 34 | 35 | If you now visit http://localhost:8181, you should see the welcome message including your username. -------------------------------------------------------------------------------- /application/phoenix/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM elixir:1.9.4-alpine 2 | 3 | # Install SecretHub 4 | RUN apk add --repository https://alpine.secrethub.io/alpine/edge/main --allow-untrusted secrethub-cli 5 | 6 | RUN mix local.hex --force 7 | RUN mix archive.install hex phx_new 1.5.4 --force 8 | RUN mix phx.new example --no-ecto 9 | 10 | EXPOSE 4000 11 | 12 | COPY ./example /example/lib/example_web 13 | WORKDIR ./example 14 | 15 | RUN mix deps.get --force 16 | RUN mix local.rebar --force 17 | 18 | ENTRYPOINT ["secrethub", "run", "--"] 19 | CMD ["mix", "phx.server"] 20 | -------------------------------------------------------------------------------- /application/phoenix/README.md: -------------------------------------------------------------------------------- 1 |

2 | Phoenix + SecretHub 3 |

4 |
5 | 6 | This Phoenix example checks if the environment variables `DEMO_USERNAME` and `DEMO_PASSWORD` have been set. If that's the case, you'll receive a personalized greeting message on http://localhost:4000, otherwise you will get an error message. 7 | 8 | ## Prerequisites 9 | 1. [Docker](https://docs.docker.com/install/) installed and running 10 | 1. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 11 | 1. A SecretHub repo that contains a `username` and `password` secret. To create it, run `secrethub demo init`. 12 | 13 | ## Running the example 14 | 15 | Set the SecretHub username in an environment variable 16 | ``` 17 | export SECRETHUB_USERNAME= 18 | ``` 19 | 20 | Create a service account for the demo repo 21 | ``` 22 | secrethub service init --description demo_service \ 23 | --permission read --file demo_service.cred ${SECRETHUB_USERNAME}/demo 24 | ``` 25 | 26 | Build the Phoenix docker demo 27 | ``` 28 | docker build . -t phoenix-secrethub-demo 29 | ``` 30 | 31 | Run the docker demo with the secrets in the environment variables 32 | ``` 33 | docker run -p 4000:4000 \ 34 | -e DEMO_USERNAME=secrethub://${SECRETHUB_USERNAME}/demo/username \ 35 | -e DEMO_PASSWORD=secrethub://${SECRETHUB_USERNAME}/demo/password \ 36 | -e SECRETHUB_CREDENTIAL=$(cat demo_service.cred) \ 37 | phoenix-secrethub-demo 38 | ``` 39 | 40 | If you now visit http://localhost:4000, you should see the welcome message including your username. 41 | -------------------------------------------------------------------------------- /application/phoenix/example/controllers/example_controller.ex: -------------------------------------------------------------------------------- 1 | defmodule Example.ExampleController do 2 | use ExampleWeb, :controller 3 | 4 | def index(conn, _params) do 5 | text conn, response() 6 | end 7 | 8 | def response() do 9 | if System.get_env("DEMO_USERNAME") != nil && System.get_env("DEMO_PASSWORD") != nil do 10 | "Hello, " <> System.get_env("DEMO_USERNAME") <> "!" 11 | else 12 | "not all the variables have been set" 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /application/phoenix/example/router.ex: -------------------------------------------------------------------------------- 1 | defmodule ExampleWeb.Router do 2 | use ExampleWeb, :router 3 | 4 | pipeline :api do 5 | plug :accepts, ["html"] 6 | end 7 | 8 | scope "/", Example do 9 | pipe_through :api # Use the default browser stack 10 | 11 | get "/", ExampleController, :index 12 | end 13 | 14 | end 15 | -------------------------------------------------------------------------------- /application/play/README.md: -------------------------------------------------------------------------------- 1 |

2 | Play + SecretHub 3 |

4 |
5 | 6 | This Play example checks if the environment variables `DEMO_USERNAME` and `DEMO_PASSWORD` have been set. If that's the case, you'll receive a `200` on http://localhost:9000 and if it's not, you'll get a `500`. 7 | 8 | ## Prerequisites 9 | 1. [Docker](https://docs.docker.com/install/) installed and running 10 | 1. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 11 | 1. A SecretHub repo that contains a `username` and `password` secret. To create it, run `secrethub demo init`. 12 | 13 | ## Running the example 14 | 15 | Set the SecretHub username in an environment variable 16 | ``` 17 | export SECRETHUB_USERNAME= 18 | ``` 19 | 20 | Create a service account for the demo repo 21 | ``` 22 | secrethub service init --description demo_service \ 23 | --permission read --file demo_service.cred ${SECRETHUB_USERNAME}/demo 24 | ``` 25 | 26 | Build the play docker demo. You can choose `java` or `scala`, depending on which language you want to see the example in action. 27 | ``` 28 | docker build {java | scala} -t play-secrethub-demo 29 | ``` 30 | 31 | Run the docker demo with the secrets in the environment variables 32 | ``` 33 | docker run -ti -p 9000:9000 \ 34 | -e DEMO_USERNAME=secrethub://${SECRETHUB_USERNAME}/demo/username \ 35 | -e DEMO_PASSWORD=secrethub://${SECRETHUB_USERNAME}/demo/password \ 36 | -e SECRETHUB_CREDENTIAL=$(cat demo_service.cred) \ 37 | play-secrethub-demo 38 | ``` 39 | 40 | If you now visit http://localhost:9000, you should see the welcome message including your username. 41 | 42 | -------------------------------------------------------------------------------- /application/play/java/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mozilla/sbt:latest 2 | 3 | # Install SecretHub 4 | RUN curl -sLJO https://deb.secrethub.io/amd64 5 | RUN dpkg -i secrethub-cli-amd64.deb 6 | RUN rm secrethub-cli-amd64.deb 7 | 8 | COPY example ./example/ 9 | 10 | WORKDIR ./example/ 11 | 12 | # Download project's dependencies 13 | RUN sbt update 14 | 15 | # Expose Play Framework standard port 9000 16 | EXPOSE 9000 17 | 18 | # Add the SecretHub entrypoint 19 | ENTRYPOINT ["secrethub", "run", "--"] 20 | 21 | # Start the main process 22 | CMD ["sbt", "run"] 23 | 24 | -------------------------------------------------------------------------------- /application/play/java/example/.gitignore: -------------------------------------------------------------------------------- 1 | logs 2 | target 3 | /.idea 4 | /.idea_modules 5 | /.classpath 6 | /.project 7 | /.settings 8 | /RUNNING_PID 9 | -------------------------------------------------------------------------------- /application/play/java/example/app/controllers/HomeController.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import play.mvc.*; 4 | 5 | /** 6 | * This controller contains an action to handle HTTP requests 7 | * to the application's home page. 8 | */ 9 | public class HomeController extends Controller { 10 | 11 | /** 12 | * An action that renders an HTML page with a welcome message. 13 | * The configuration in the routes file means that 14 | * this method will be called when the application receives a 15 | * GET request with a path of /. 16 | */ 17 | public Result index() { 18 | if (System.getenv("DEMO_USERNAME") == null || System.getenv("DEMO_PASSWORD") == null) { 19 | return Results.internalServerError("not all variables are set\n"); 20 | } else { 21 | return ok("Welcome " + System.getenv("DEMO_USERNAME") + "\n"); 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /application/play/java/example/build.sbt: -------------------------------------------------------------------------------- 1 | name := """example""" 2 | organization := "com.example" 3 | 4 | version := "1.0-SNAPSHOT" 5 | 6 | lazy val root = (project in file(".")).enablePlugins(PlayJava) 7 | 8 | scalaVersion := "2.13.3" 9 | 10 | libraryDependencies += guice 11 | -------------------------------------------------------------------------------- /application/play/java/example/conf/application.conf: -------------------------------------------------------------------------------- 1 | # This is the main configuration file for the application. 2 | # https://www.playframework.com/documentation/latest/ConfigFile 3 | -------------------------------------------------------------------------------- /application/play/java/example/conf/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ${application.home:-.}/logs/application.log 8 | 9 | UTF-8 10 | 11 | %d{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) %cyan(%logger{36}) %magenta(%X{akkaSource}) %msg%n 12 | 13 | 14 | 15 | 16 | 17 | true 18 | 19 | UTF-8 20 | 21 | %d{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) %cyan(%logger{36}) %magenta(%X{akkaSource}) %msg%n 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /application/play/java/example/conf/routes: -------------------------------------------------------------------------------- 1 | # Routes 2 | # This file defines all application routes (Higher priority routes first) 3 | # ~~~~ 4 | 5 | # An example controller showing a sample home page 6 | GET / controllers.HomeController.index 7 | 8 | # Map static resources from the /public folder to the /assets URL path 9 | GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset) 10 | -------------------------------------------------------------------------------- /application/play/java/example/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.3.13 2 | -------------------------------------------------------------------------------- /application/play/java/example/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | // The Play plugin 2 | addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.7") 3 | 4 | // Defines scaffolding (found under .g8 folder) 5 | // http://www.foundweekends.org/giter8/scaffolding.html 6 | // sbt "g8Scaffold form" 7 | addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.11.0") 8 | -------------------------------------------------------------------------------- /application/play/java/example/test/controllers/HomeControllerTest.java: -------------------------------------------------------------------------------- 1 | package controllers; 2 | 3 | import org.junit.Test; 4 | import play.Application; 5 | import play.inject.guice.GuiceApplicationBuilder; 6 | import play.mvc.Http; 7 | import play.mvc.Result; 8 | import play.test.WithApplication; 9 | 10 | import static org.junit.Assert.assertEquals; 11 | import static play.mvc.Http.Status.*; 12 | import static play.test.Helpers.GET; 13 | import static play.test.Helpers.route; 14 | 15 | public class HomeControllerTest extends WithApplication { 16 | 17 | @Override 18 | protected Application provideApplication() { 19 | return new GuiceApplicationBuilder().build(); 20 | } 21 | 22 | @Test 23 | public void testIndex() { 24 | Http.RequestBuilder request = new Http.RequestBuilder() 25 | .method(GET) 26 | .uri("/"); 27 | 28 | Result result = route(app, request); 29 | if (System.getenv("DEMO_USERNAME") == null || System.getenv("DEMO_PASSWORD") == null) { 30 | assertEquals(INTERNAL_SERVER_ERROR, result.status()); 31 | } else { 32 | assertEquals(OK, result.status()); 33 | } 34 | } 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /application/play/scala/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mozilla/sbt:latest 2 | 3 | # Install SecretHub 4 | RUN curl -sLJO https://deb.secrethub.io/amd64 5 | RUN dpkg -i secrethub-cli-amd64.deb 6 | RUN rm secrethub-cli-amd64.deb 7 | 8 | COPY example ./example/ 9 | 10 | WORKDIR ./example/ 11 | 12 | # Download project's dependencies 13 | RUN sbt update 14 | 15 | # Expose Play Framework standard port 9000 16 | EXPOSE 9000 17 | 18 | # Add the SecretHub entrypoint 19 | ENTRYPOINT ["secrethub", "run", "--"] 20 | 21 | # Start the main process 22 | CMD ["sbt", "run"] 23 | 24 | -------------------------------------------------------------------------------- /application/play/scala/example/.gitignore: -------------------------------------------------------------------------------- 1 | logs 2 | target 3 | /.idea 4 | /.idea_modules 5 | /.classpath 6 | /.project 7 | /.settings 8 | /RUNNING_PID 9 | -------------------------------------------------------------------------------- /application/play/scala/example/app/controllers/HomeController.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import javax.inject._ 4 | import play.api._ 5 | import play.api.mvc._ 6 | 7 | /** 8 | * This controller creates an `Action` to handle HTTP requests to the 9 | * application's home page. 10 | */ 11 | @Singleton 12 | class HomeController @Inject()(val controllerComponents: ControllerComponents) extends BaseController { 13 | 14 | /** 15 | * Create an Action to render an HTML page. 16 | * 17 | * The configuration in the `routes` file means that this method 18 | * will be called when the application receives a `GET` request with 19 | * a path of `/`. 20 | */ 21 | def index() = Action { implicit request: Request[AnyContent] => 22 | if (sys.env.getOrElse("DEMO_USERNAME", "").isEmpty || sys.env.getOrElse("DEMO_PASSWORD", "").isEmpty) { 23 | InternalServerError("not all variables are set\n") 24 | } else { 25 | Ok("Welcome " + sys.env("DEMO_USERNAME") + "\n") 26 | } 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /application/play/scala/example/build.sbt: -------------------------------------------------------------------------------- 1 | name := """example""" 2 | organization := "com.example" 3 | 4 | version := "1.0-SNAPSHOT" 5 | 6 | lazy val root = (project in file(".")).enablePlugins(PlayScala) 7 | 8 | scalaVersion := "2.13.3" 9 | 10 | libraryDependencies += guice 11 | libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "5.0.0" % Test 12 | 13 | // Adds additional packages into Twirl 14 | //TwirlKeys.templateImports += "com.example.controllers._" 15 | 16 | // Adds additional packages into conf/routes 17 | // play.sbt.routes.RoutesKeys.routesImport += "com.example.binders._" 18 | -------------------------------------------------------------------------------- /application/play/scala/example/conf/application.conf: -------------------------------------------------------------------------------- 1 | # https://www.playframework.com/documentation/latest/Configuration 2 | -------------------------------------------------------------------------------- /application/play/scala/example/conf/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ${application.home:-.}/logs/application.log 8 | 9 | UTF-8 10 | 11 | %d{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) %cyan(%logger{36}) %magenta(%X{akkaSource}) %msg%n 12 | 13 | 14 | 15 | 16 | 17 | true 18 | 19 | UTF-8 20 | 21 | %d{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) %cyan(%logger{36}) %magenta(%X{akkaSource}) %msg%n 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /application/play/scala/example/conf/messages: -------------------------------------------------------------------------------- 1 | # https://www.playframework.com/documentation/latest/ScalaI18N 2 | -------------------------------------------------------------------------------- /application/play/scala/example/conf/routes: -------------------------------------------------------------------------------- 1 | # Routes 2 | # This file defines all application routes (Higher priority routes first) 3 | # https://www.playframework.com/documentation/latest/ScalaRouting 4 | # ~~~~ 5 | 6 | # An example controller showing a sample home page 7 | GET / controllers.HomeController.index 8 | 9 | # Map static resources from the /public folder to the /assets URL path 10 | GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset) 11 | -------------------------------------------------------------------------------- /application/play/scala/example/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.3.13 2 | -------------------------------------------------------------------------------- /application/play/scala/example/project/plugins.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.7") 2 | addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.11.0") 3 | -------------------------------------------------------------------------------- /application/play/scala/example/test/controllers/HomeControllerSpec.scala: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import org.scalatestplus.play._ 4 | import org.scalatestplus.play.guice._ 5 | import play.api.test._ 6 | import play.api.test.Helpers._ 7 | 8 | /** 9 | * Add your spec here. 10 | * You can mock out a whole application including requests, plugins etc. 11 | * 12 | * For more information, see https://www.playframework.com/documentation/latest/ScalaTestingWithScalaTest 13 | */ 14 | class HomeControllerSpec extends PlaySpec with GuiceOneAppPerTest with Injecting { 15 | 16 | def checkCredentials(negativeCase: Int): Int = { 17 | if (sys.env.getOrElse("DEMO_USERNAME", "").isEmpty || sys.env.getOrElse("DEMO_PASSWORD", "").isEmpty) negativeCase 18 | else OK 19 | } 20 | 21 | def credentialMessage(): String = { 22 | if (sys.env.getOrElse("DEMO_USERNAME", "").isEmpty || sys.env.getOrElse("DEMO_PASSWORD", "").isEmpty) "not all variables are set" 23 | else "Welcome" 24 | } 25 | 26 | def routeContentType(): Some[String] = { 27 | if (sys.env.getOrElse("DEMO_USERNAME", "").isEmpty || sys.env.getOrElse("DEMO_PASSWORD", "").isEmpty) Some("text/html") 28 | else Some("text/plain") 29 | } 30 | 31 | def routeCredentialMessage(): String = { 32 | if (sys.env.getOrElse("DEMO_USERNAME", "").isEmpty || sys.env.getOrElse("DEMO_PASSWORD", "").isEmpty) "Not Found" 33 | else "Welcome" 34 | } 35 | 36 | "HomeController GET" should { 37 | 38 | "render the index page from a new instance of controller" in { 39 | val controller = new HomeController(stubControllerComponents()) 40 | val home = controller.index().apply(FakeRequest(GET, "/")) 41 | 42 | status(home) mustBe checkCredentials(INTERNAL_SERVER_ERROR) 43 | contentType(home) mustBe Some("text/plain") 44 | contentAsString(home) must include (credentialMessage()) 45 | } 46 | 47 | "render the index page from the application" in { 48 | val controller = inject[HomeController] 49 | val home = controller.index().apply(FakeRequest(GET, "/")) 50 | 51 | status(home) mustBe checkCredentials(INTERNAL_SERVER_ERROR) 52 | contentType(home) mustBe Some("text/plain") 53 | contentAsString(home) must include (credentialMessage()) 54 | } 55 | 56 | "render the index page from the router" in { 57 | val request = FakeRequest(GET, "/") 58 | val home = route(app, request).get 59 | 60 | status(home) mustBe checkCredentials(NOT_FOUND) 61 | contentType(home) mustBe routeContentType() 62 | contentAsString(home) must include (routeCredentialMessage()) 63 | } 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /application/rails/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:2.7 2 | RUN mkdir /myapp 3 | WORKDIR /myapp 4 | 5 | # Install SecretHub 6 | RUN echo "deb [trusted=yes] https://apt.secrethub.io stable main" > /etc/apt/sources.list.d/secrethub.sources.list && apt-get update 7 | RUN apt-get install -y secrethub-cli 8 | 9 | # Install rails 10 | RUN gem install rails 11 | 12 | # Create Secrethub Demo app 13 | RUN rails new secrethub_demo --api --skip-active-record 14 | 15 | # Copy source files 16 | COPY routes.rb /myapp/secrethub_demo/config/routes.rb 17 | COPY application_controller.rb /myapp/secrethub_demo/app/controllers/application_controller.rb 18 | 19 | # Change workdir 20 | WORKDIR /myapp/secrethub_demo/ 21 | 22 | # Expose rails standard port 23 | EXPOSE 3000 24 | 25 | # Add the secrethub entrypoint 26 | ENTRYPOINT ["secrethub", "run", "--"] 27 | 28 | # Start the main process 29 | CMD ["rails", "server", "-b", "0.0.0.0"] 30 | -------------------------------------------------------------------------------- /application/rails/README.md: -------------------------------------------------------------------------------- 1 |

2 | Rails + SecretHub 3 |

4 |
5 | 6 | This Ruby on Rails example checks if the environment variables `DEMO_USERNAME` and `DEMO_PASSWORD` have been set. If that's the case, you'll receive a `200` on http://localhost:8080 and if it's not, you'll get a `500`. 7 | 8 | ## Prerequisites 9 | 1. [Docker](https://docs.docker.com/install/) installed and running 10 | 1. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 11 | 1. A SecretHub repo that contains a `username` and `password` secret. To create it, run `secrethub demo init`. 12 | 13 | ## Running the example 14 | 15 | Set the SecretHub username in an environment variable 16 | ``` 17 | export SECRETHUB_USERNAME= 18 | ``` 19 | 20 | Create a service account for the demo repo 21 | ``` 22 | secrethub service init --description demo_service \ 23 | --permission read --file demo_service.cred ${SECRETHUB_USERNAME}/demo 24 | ``` 25 | 26 | Build the rails docker demo 27 | ``` 28 | docker build . -t rails-secrethub-demo 29 | ``` 30 | 31 | Run the docker demo with the secrets in the environment variables 32 | ``` 33 | docker run -ti -p 8080:3000 \ 34 | -e DEMO_USERNAME=secrethub://${SECRETHUB_USERNAME}/demo/username \ 35 | -e DEMO_PASSWORD=secrethub://${SECRETHUB_USERNAME}/demo/password \ 36 | -e SECRETHUB_CREDENTIAL=$(cat demo_service.cred) \ 37 | rails-secrethub-demo 38 | ``` 39 | 40 | If you now visit http://localhost:8080, you should see the welcome message including your username. 41 | -------------------------------------------------------------------------------- /application/rails/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::API 2 | def index 3 | if ENV['DEMO_USERNAME'] && ENV['DEMO_PASSWORD'] 4 | render status: 200, html: "Welcome " + ENV['DEMO_USERNAME'] 5 | else 6 | render status: 500, html: 'not all variables are set' 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /application/rails/routes.rb: -------------------------------------------------------------------------------- 1 | # config/routes.rb 2 | Rails.application.routes.draw do 3 | root to: 'application#index' 4 | end 5 | -------------------------------------------------------------------------------- /application/ruby/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:2.7-slim 2 | WORKDIR /app 3 | COPY . /app 4 | 5 | # Install SecretHub 6 | RUN echo "deb [trusted=yes] https://apt.secrethub.io stable main" > /etc/apt/sources.list.d/secrethub.sources.list && apt-get update 7 | RUN apt-get install -y secrethub-cli 8 | 9 | # Install Gemfile 10 | RUN bundle update 11 | RUN bundle install 12 | 13 | # Expose ruby standard port 4567 14 | EXPOSE 4567 15 | 16 | # Add the secrethub entrypoint 17 | ENTRYPOINT ["secrethub", "run", "--"] 18 | 19 | # Start the main process 20 | CMD ["ruby", "myapp.rb"] 21 | -------------------------------------------------------------------------------- /application/ruby/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'sinatra' 4 | gem 'sinatra-contrib' 5 | -------------------------------------------------------------------------------- /application/ruby/README.md: -------------------------------------------------------------------------------- 1 | # Ruby application in Docker 2 | 3 | This Ruby example checks if the environment variables `DEMO_USERNAME` and `DEMO_PASSWORD` have been set. If that's the case, you'll receive a `200` on http://localhost:8080 and if it's not, you'll get a `500`. 4 | 5 | ## Prerequisites 6 | 1. [Docker](https://docs.docker.com/install/) installed and running 7 | 1. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 8 | 1. A SecretHub repo that contains a `username` and `password` secret. To create it, run `secrethub demo init`. 9 | 10 | ## Running the example 11 | 12 | Set the SecretHub username in an environment variable 13 | ``` 14 | export SECRETHUB_USERNAME= 15 | ``` 16 | 17 | Create a service account for the demo repo 18 | ``` 19 | secrethub service init --description demo_service \ 20 | --permission read --file demo_service.cred ${SECRETHUB_USERNAME}/demo 21 | ``` 22 | 23 | Build the ruby docker demo 24 | ``` 25 | docker build . -t ruby-secrethub-demo 26 | ``` 27 | 28 | Run the docker demo with the secrets in the environment variables 29 | ``` 30 | docker run -ti -p 8080:4567 \ 31 | -e DEMO_USERNAME=secrethub://${SECRETHUB_USERNAME}/demo/username \ 32 | -e DEMO_PASSWORD=secrethub://${SECRETHUB_USERNAME}/demo/password \ 33 | -e SECRETHUB_CREDENTIAL=$(cat demo_service.cred) \ 34 | ruby-secrethub-demo 35 | ``` 36 | 37 | If you now visit http://localhost:8080, you should see the welcome message including your username. 38 | -------------------------------------------------------------------------------- /application/ruby/myapp.rb: -------------------------------------------------------------------------------- 1 | # myapp.rb 2 | require 'sinatra' 3 | 4 | port = ENV['PORT'] || 4567 5 | puts "Starting ruby-secrethub-demo on port #{port}" 6 | set :port, port 7 | set :bind, '0.0.0.0' 8 | 9 | if ENV['DEMO_USERNAME'] && ENV['DEMO_PASSWORD'] 10 | status = 200 11 | content = "Welcome " + ENV['DEMO_USERNAME'] 12 | else 13 | status = 500 14 | content = 'not all variables are set' 15 | end 16 | 17 | get '/' do 18 | status status 19 | body content 20 | end 21 | -------------------------------------------------------------------------------- /application/spring-boot/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build app using Maven 2 | FROM maven:3-jdk-8 AS build 3 | 4 | WORKDIR /build 5 | 6 | COPY pom.xml . 7 | 8 | RUN mvn dependency:resolve 9 | 10 | COPY src/ src/ 11 | 12 | RUN mvn package 13 | 14 | # Run app 15 | FROM openjdk:8-jdk-alpine 16 | COPY --from=build /build/target/example-*.jar /example.jar 17 | 18 | # Install SecretHub 19 | RUN apk add --repository https://alpine.secrethub.io/alpine/edge/main --allow-untrusted secrethub-cli 20 | 21 | # Expose spring boot standard port 8080 22 | EXPOSE 8080 23 | 24 | # Add the SecretHub entrypoint 25 | ENTRYPOINT ["secrethub", "run", "--"] 26 | 27 | # Start the main process 28 | CMD ["java", "-jar", "/example.jar"] 29 | -------------------------------------------------------------------------------- /application/spring-boot/README.md: -------------------------------------------------------------------------------- 1 |

2 | Spring Boot + SecretHub 3 |

4 |
5 | 6 | This Spring Boot example checks if the environment variables `DEMO_USERNAME` and `DEMO_PASSWORD` have been set. If that's the case, you'll receive a `200` on http://localhost:8080 and if it's not, you'll get a `500`. 7 | 8 | ## Prerequisites 9 | 1. [Docker](https://docs.docker.com/install/) installed and running 10 | 1. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 11 | 1. A SecretHub repo that contains a `username` and `password` secret. To create it, run `secrethub demo init`. 12 | 13 | ## Running the example 14 | 15 | Set the SecretHub username in an environment variable 16 | ``` 17 | export SECRETHUB_USERNAME= 18 | ``` 19 | 20 | Create a service account for the demo repo 21 | ``` 22 | secrethub service init --description demo_service \ 23 | --permission read --file demo_service.cred ${SECRETHUB_USERNAME}/demo 24 | ``` 25 | 26 | Build the spring-boot docker demo 27 | ``` 28 | docker build . -t spring-secrethub-demo 29 | ``` 30 | 31 | Run the docker demo with the secrets in the environment variables 32 | ``` 33 | docker run -ti -p 8080:8080 \ 34 | -e DEMO_USERNAME=secrethub://${SECRETHUB_USERNAME}/demo/username \ 35 | -e DEMO_PASSWORD=secrethub://${SECRETHUB_USERNAME}/demo/password \ 36 | -e SECRETHUB_CREDENTIAL=$(cat demo_service.cred) \ 37 | spring-secrethub-demo 38 | ``` 39 | 40 | If you now visit http://localhost:8080, you should see the welcome message including your username. 41 | -------------------------------------------------------------------------------- /application/spring-boot/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework 7 | example 8 | 0.1.0 9 | 10 | 11 | org.springframework.boot 12 | spring-boot-starter-parent 13 | 2.2.1.RELEASE 14 | 15 | 16 | 17 | 1.8 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-web 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-test 28 | test 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-maven-plugin 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /application/spring-boot/src/main/java/example/ExampleApplication.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | 12 | @SpringBootApplication 13 | public class ExampleApplication { 14 | 15 | @Value("${DEMO_USERNAME:#{null}}") 16 | String username; 17 | 18 | @Value("${DEMO_PASSWORD:#{null}}") 19 | String password; 20 | 21 | @RestController 22 | class ExampleController { 23 | @GetMapping("/") 24 | ResponseEntity printSecrets() { 25 | if (username==null || password==null) { 26 | return new ResponseEntity<>("not all variables are set", HttpStatus.INTERNAL_SERVER_ERROR); 27 | } else { 28 | return new ResponseEntity<>("Welcome " + username, HttpStatus.OK); 29 | } 30 | } 31 | } 32 | 33 | public static void main(String[] args) { 34 | SpringApplication.run(ExampleApplication.class, args); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /aws/ec2/README.md: -------------------------------------------------------------------------------- 1 |

2 | AWS EC2 + SecretHub 3 |

4 |
5 | 6 |

7 | View Docs 8 |

9 |
10 | 11 | This example uses Terraform to launch an EC2 instance, deploy the [SecretHub Demo App](https://secrethub.io/docs/start/getting-started/#consume) on it and provision it with the required secrets using the [SecretHub AWS Identity Provider](https://secrethub.io/docs/reference/aws/). 12 | 13 | ## Prerequisites 14 | 1. [Terraform](https://www.terraform.io/downloads.html) installed along with the [SecretHub Provider](https://secrethub.io/docs/guides/terraform/#install) 15 | 1. Correctly configured [AWS Credentials](https://www.terraform.io/docs/providers/aws/index.html#authentication) 16 | 1. [Values assigned](https://www.terraform.io/docs/configuration/variables.html#assigning-values-to-root-module-variables) to the variables in [variables.tf](./variables.tf) 17 | 18 | ## Running the example 19 | 20 | To launch an example EC2 instance (`t2.nano`), that runs the demo app, run: 21 | ``` 22 | terraform init 23 | terraform apply 24 | ``` 25 | 26 | Once the instance is running its public IP will be outputted. 27 | 28 | To see the app running, visit `http://:8080`. 29 | 30 | > Note that it might take a couple minutes for the instance to be accessible from the browser. 31 | -------------------------------------------------------------------------------- /aws/ec2/app.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_role" "secrethub_demo" { 2 | name = "SecretHubDemoEC2Role" 3 | assume_role_policy = data.aws_iam_policy_document.ec2_assume_role.json 4 | description = "Role for SecretHub demo app" 5 | } 6 | 7 | data "aws_iam_policy_document" "ec2_assume_role" { 8 | statement { 9 | actions = ["sts:AssumeRole"] 10 | 11 | principals { 12 | type = "Service" 13 | identifiers = ["ec2.amazonaws.com"] 14 | } 15 | } 16 | } 17 | 18 | resource "aws_kms_key" "secrethub_auth" { 19 | description = "KMS key to facilitate SecretHub authentication" 20 | } 21 | 22 | data "aws_iam_policy_document" "secrethub_auth" { 23 | statement { 24 | actions = ["kms:Decrypt"] 25 | resources = [aws_kms_key.secrethub_auth.arn] 26 | effect = "Allow" 27 | } 28 | } 29 | 30 | resource "aws_iam_policy" "secrethub_auth" { 31 | name = "SecretHubAuth" 32 | description = "Allow SecretHub authentication using KMS" 33 | policy = data.aws_iam_policy_document.secrethub_auth.json 34 | } 35 | 36 | resource "aws_iam_role_policy_attachment" "secrethub_demo_auth" { 37 | role = aws_iam_role.secrethub_demo.name 38 | policy_arn = aws_iam_policy.secrethub_auth.arn 39 | } 40 | 41 | resource "secrethub_service_aws" "demo_app" { 42 | repo = var.secrethub_repo 43 | role = aws_iam_role.secrethub_demo.name 44 | kms_key_arn = aws_kms_key.secrethub_auth.arn 45 | } 46 | 47 | resource "secrethub_access_rule" "demo_app" { 48 | account_name = secrethub_service_aws.demo_app.id 49 | dir = var.secrethub_repo 50 | permission = "read" 51 | } 52 | 53 | data "aws_ami" "amazon_linux" { 54 | owners = ["amazon"] 55 | most_recent = true 56 | 57 | filter { 58 | name = "name" 59 | values = ["amzn-ami-hvm-*-x86_64-gp2"] 60 | } 61 | } 62 | 63 | resource "aws_instance" "secrethub_demo" { 64 | instance_type = "t2.nano" 65 | ami = data.aws_ami.amazon_linux.id 66 | iam_instance_profile = aws_iam_instance_profile.secrethub_demo.name 67 | security_groups = [aws_security_group.secrethub_demo.name] 68 | associate_public_ip_address = true 69 | user_data = <<-EOT 70 | #! /bin/bash 71 | sudo curl https://yum.secrethub.io/secrethub.repo --output /etc/yum/repos.d/secrethub.repo --create-dirs 72 | sudo yum install -y secrethub-cli 73 | export DEMO_USERNAME=secrethub://${var.secrethub_repo}/username 74 | export DEMO_PASSWORD=secrethub://${var.secrethub_repo}/password 75 | secrethub run --identity-provider=aws -- secrethub demo serve --host 0.0.0.0 --port ${var.port} 76 | EOT 77 | } 78 | 79 | resource "aws_iam_instance_profile" "secrethub_demo" { 80 | role = aws_iam_role.secrethub_demo.name 81 | } 82 | 83 | resource "aws_security_group" "secrethub_demo" { 84 | description = "SecretHub demo app" 85 | 86 | ingress { 87 | from_port = var.port 88 | to_port = var.port 89 | protocol = "tcp" 90 | cidr_blocks = ["0.0.0.0/0"] 91 | } 92 | 93 | egress { 94 | from_port = 0 95 | to_port = 0 96 | protocol = "-1" 97 | cidr_blocks = ["0.0.0.0/0"] 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /aws/ec2/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | secrethub = { 4 | source = "secrethub/secrethub" 5 | version = "~> 1.2.3" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /aws/ec2/outputs.tf: -------------------------------------------------------------------------------- 1 | output "public_ip" { 2 | value = aws_instance.secrethub_demo.public_ip 3 | } 4 | -------------------------------------------------------------------------------- /aws/ec2/variables.tf: -------------------------------------------------------------------------------- 1 | variable "secrethub_repo" { 2 | description = "SecretHub repo that contains the demo `username` and `password` secrets. To create this repo, run `secrethub demo init`." 3 | } 4 | 5 | variable "port" { 6 | description = "Port to publicly expose on the EC2 node, where the demo app will listen on." 7 | default = 8080 8 | } 9 | -------------------------------------------------------------------------------- /aws/ecs/README.md: -------------------------------------------------------------------------------- 1 |

2 | AWS ECS + SecretHub 3 |

4 |
5 | 6 |

7 | View Docs 8 |

9 |
10 | 11 | # Deploying to AWS ECS using Terraform 12 | This example creates an ECS cluster and deploys the [SecretHub Demo App](https://secrethub.io/docs/start/getting-started/#consume) to it and provisions it with the required secrets using the [SecretHub AWS Identity Provider](https://secrethub.io/docs/reference/aws/). 13 | 14 | ## Prerequisites 15 | 1. [Terraform](https://www.terraform.io/downloads.html) installed along with the [SecretHub Provider](https://secrethub.io/docs/guides/terraform/#install) 16 | 1. Correctly configured [AWS Credentials](https://www.terraform.io/docs/providers/aws/index.html#authentication) 17 | 1. [Values assigned](https://www.terraform.io/docs/configuration/variables.html#assigning-values-to-root-module-variables) to the variables in [variables.tf](./variables.tf) 18 | 19 | ## Running the example 20 | 21 | Init the SecretHub demo repo with example values 22 | ``` 23 | secrethub demo init 24 | ``` 25 | 26 | To launch an example ECS cluster, run: 27 | ``` 28 | terraform init 29 | terraform apply 30 | ``` 31 | 32 | Get the public IP of the cluster from the AWS console or using the AWS CLI and visit `http://:8080` to see the app running. 33 | -------------------------------------------------------------------------------- /aws/ecs/app.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_role" "secrethub_demo" { 2 | name = "SecretHubDemoECSTaskRole" 3 | assume_role_policy = data.aws_iam_policy_document.ecs_assume_role.json 4 | description = "Role for SecretHub demo app" 5 | } 6 | 7 | data "aws_iam_policy_document" "ecs_assume_role" { 8 | statement { 9 | actions = ["sts:AssumeRole"] 10 | 11 | principals { 12 | type = "Service" 13 | identifiers = ["ecs-tasks.amazonaws.com"] 14 | } 15 | } 16 | } 17 | 18 | resource "aws_kms_key" "secrethub_auth" { 19 | description = "KMS key to facilitate SecretHub authentication" 20 | } 21 | 22 | data "aws_iam_policy_document" "secrethub_auth" { 23 | statement { 24 | actions = ["kms:Decrypt"] 25 | resources = [aws_kms_key.secrethub_auth.arn] 26 | effect = "Allow" 27 | } 28 | } 29 | 30 | resource "aws_iam_policy" "secrethub_auth" { 31 | name = "SecretHubAuth" 32 | description = "Allow SecretHub authentication using KMS" 33 | policy = data.aws_iam_policy_document.secrethub_auth.json 34 | } 35 | 36 | resource "aws_iam_role_policy_attachment" "secrethub_demo_auth" { 37 | role = aws_iam_role.secrethub_demo.name 38 | policy_arn = aws_iam_policy.secrethub_auth.arn 39 | } 40 | 41 | resource "secrethub_service_aws" "demo_app" { 42 | repo = var.secrethub_repo 43 | role = aws_iam_role.secrethub_demo.name 44 | kms_key_arn = aws_kms_key.secrethub_auth.arn 45 | } 46 | resource "secrethub_access_rule" "demo_app" { 47 | account_name = secrethub_service_aws.demo_app.id 48 | dir = var.secrethub_repo 49 | permission = "read" 50 | } 51 | 52 | data "aws_iam_role" "ecs_execution_role" { 53 | name = "ecsTaskExecutionRole" 54 | } 55 | 56 | resource "aws_ecs_task_definition" "secrethub_demo" { 57 | family = "SecretHubDemo" 58 | cpu = "256" 59 | memory = "512" 60 | requires_compatibilities = ["FARGATE"] 61 | network_mode = "awsvpc" 62 | execution_role_arn = data.aws_iam_role.ecs_execution_role.arn 63 | task_role_arn = aws_iam_role.secrethub_demo.arn 64 | container_definitions = jsonencode(local.container_definitions) 65 | } 66 | 67 | locals { 68 | container_definitions = [ 69 | { 70 | name = "app" 71 | image = "secrethub/demo-app" 72 | portMappings = [ 73 | { 74 | containerPort = 8080 75 | hostPort = 8080 76 | }, 77 | ] 78 | environment = [ 79 | { 80 | name = "SECRETHUB_IDENTITY_PROVIDER" 81 | value = "aws" 82 | }, 83 | { 84 | name = "DEMO_USERNAME" 85 | value = "secrethub://${var.secrethub_repo}/username" 86 | }, 87 | { 88 | name = "DEMO_PASSWORD" 89 | value = "secrethub://${var.secrethub_repo}/password" 90 | }, 91 | ] 92 | }, 93 | ] 94 | } 95 | 96 | resource "aws_ecs_service" "secrethub_demo" { 97 | name = "SecretHubDemo" 98 | cluster = aws_ecs_cluster.secrethub_demo.id 99 | launch_type = "FARGATE" 100 | task_definition = aws_ecs_task_definition.secrethub_demo.arn 101 | 102 | network_configuration { 103 | subnets = var.subnets 104 | security_groups = [aws_security_group.secrethub_demo.id] 105 | assign_public_ip = true 106 | } 107 | 108 | desired_count = 1 109 | 110 | depends_on = [ 111 | secrethub_access_rule.demo_app, 112 | ] 113 | } 114 | 115 | resource "aws_security_group" "secrethub_demo" { 116 | description = "Allow public access to SecretHub demo app" 117 | vpc_id = var.vpc_id 118 | 119 | ingress { 120 | from_port = 8080 121 | to_port = 8080 122 | protocol = "tcp" 123 | cidr_blocks = ["0.0.0.0/0"] 124 | } 125 | 126 | egress { 127 | from_port = 0 128 | to_port = 0 129 | protocol = "-1" 130 | cidr_blocks = ["0.0.0.0/0"] 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /aws/ecs/cluster.tf: -------------------------------------------------------------------------------- 1 | resource "aws_ecs_cluster" "secrethub_demo" { 2 | name = "SecretHubDemoCluster" 3 | } 4 | -------------------------------------------------------------------------------- /aws/ecs/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | secrethub = { 4 | source = "secrethub/secrethub" 5 | version = "~> 1.2.3" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /aws/ecs/variables.tf: -------------------------------------------------------------------------------- 1 | variable "secrethub_repo" { 2 | description = "SecretHub repo that contains the demo `username` and `password` secrets. To create this repo, run `secrethub demo init`." 3 | } 4 | 5 | variable "vpc_id" { 6 | description = "The VPC the ECS cluster lives in." 7 | } 8 | 9 | variable "subnets" { 10 | type = list(string) 11 | description = "The subnets the ECS service lives in." 12 | } 13 | -------------------------------------------------------------------------------- /aws/eks/README.md: -------------------------------------------------------------------------------- 1 | # SecretHub + EKS 2 | 3 | This example uses Terraform to deploy the [SecretHub Demo App](https://secrethub.io/docs/start/getting-started/#consume) on a EKS cluster and provision it with the secrets it needs using the [SecretHub AWS Identity Provider](https://secrethub.io/docs/reference/aws/). 4 | 5 | ## Prerequisites 6 | 1. [Terraform](https://www.terraform.io/downloads.html) installed along with the [SecretHub Provider](https://secrethub.io/docs/guides/terraform/#install) 7 | 1. Correctly configured [AWS Credentials](https://www.terraform.io/docs/providers/aws/index.html#authentication) 8 | 1. [Values assigned](https://www.terraform.io/docs/configuration/variables.html#assigning-values-to-root-module-variables) to the variables in [variables.tf](./variables.tf) 9 | 10 | ## Running the example 11 | 12 | To deploy the app on your cluster, run: 13 | ``` 14 | terraform init 15 | terraform apply 16 | ``` 17 | 18 | After launching it, forward the port to your local machine using `kubectl`: 19 | 20 | ``` 21 | kubectl port-forward deployment/demo-app 8080 22 | ``` 23 | 24 | To see the app running, visit [http://127.0.0.1:8080](http://127.0.0.1:8080). 25 | -------------------------------------------------------------------------------- /aws/eks/app.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_role" "demo_app" { 2 | name = "SecretHubDemoEKSRole" 3 | description = "Role for SecretHub demo app" 4 | assume_role_policy = data.aws_iam_policy_document.demo_app_assume_role.json 5 | } 6 | 7 | resource "kubernetes_service_account" "demo_app" { 8 | automount_service_account_token = true 9 | metadata { 10 | name = "demo-app" 11 | 12 | annotations = { 13 | "eks.amazonaws.com/role-arn" = aws_iam_role.demo_app.arn 14 | } 15 | } 16 | } 17 | 18 | data "aws_iam_policy_document" "demo_app_assume_role" { 19 | statement { 20 | actions = ["sts:AssumeRoleWithWebIdentity"] 21 | 22 | principals { 23 | type = "Federated" 24 | identifiers = ["${aws_iam_openid_connect_provider.cluster.arn}"] 25 | } 26 | 27 | condition { 28 | test = "StringEquals" 29 | variable = "${replace(local.oidc_issuer, "https://", "")}:sub" 30 | values = ["system:serviceaccount:default:demo-app"] 31 | } 32 | } 33 | } 34 | 35 | resource "aws_kms_key" "secrethub_auth" { 36 | description = "KMS key to facilitate SecretHub authentication" 37 | } 38 | 39 | data "aws_iam_policy_document" "secrethub_auth" { 40 | statement { 41 | actions = ["kms:Decrypt"] 42 | resources = [aws_kms_key.secrethub_auth.arn] 43 | effect = "Allow" 44 | } 45 | } 46 | 47 | resource "aws_iam_policy" "secrethub_auth" { 48 | name = "SecretHubAuth" 49 | description = "Allow SecretHub authentication using KMS" 50 | policy = data.aws_iam_policy_document.secrethub_auth.json 51 | } 52 | 53 | resource "aws_iam_role_policy_attachment" "demo_app_secrethub" { 54 | role = aws_iam_role.demo_app.name 55 | policy_arn = aws_iam_policy.secrethub_auth.arn 56 | } 57 | 58 | resource "secrethub_service_aws" "demo_app" { 59 | repo = var.secrethub_repo 60 | role = aws_iam_role.demo_app.name 61 | kms_key_arn = aws_kms_key.secrethub_auth.arn 62 | } 63 | 64 | resource "secrethub_access_rule" "demo_app" { 65 | account_name = secrethub_service_aws.demo_app.id 66 | dir = var.secrethub_repo 67 | permission = "read" 68 | } 69 | 70 | resource "kubernetes_deployment" "demo_app" { 71 | metadata { 72 | name = "demo-app" 73 | labels = { 74 | run = "demo-app" 75 | } 76 | } 77 | spec { 78 | replicas = 1 79 | selector { 80 | match_labels = { 81 | run = "demo-app" 82 | } 83 | } 84 | template { 85 | metadata { 86 | labels = { 87 | run = "demo-app" 88 | } 89 | } 90 | spec { 91 | service_account_name = kubernetes_service_account.demo_app.metadata[0].name 92 | automount_service_account_token = true 93 | 94 | container { 95 | image = "secrethub/demo-app" 96 | name = "demo-app" 97 | port { 98 | container_port = 8080 99 | } 100 | env { 101 | name = "SECRETHUB_IDENTITY_PROVIDER" 102 | value = "aws" 103 | } 104 | env { 105 | name = "DEMO_USERNAME" 106 | value = "secrethub://${var.secrethub_repo}/username" 107 | } 108 | env { 109 | name = "DEMO_PASSWORD" 110 | value = "secrethub://${var.secrethub_repo}/password" 111 | } 112 | } 113 | } 114 | } 115 | } 116 | 117 | wait_for_rollout = false 118 | depends_on = [ 119 | secrethub_access_rule.demo_app, 120 | ] 121 | } 122 | -------------------------------------------------------------------------------- /aws/eks/cluster.tf: -------------------------------------------------------------------------------- 1 | data "aws_eks_cluster" "cluster" { 2 | name = module.cluster.cluster_id 3 | } 4 | 5 | data "aws_eks_cluster_auth" "cluster" { 6 | name = module.cluster.cluster_id 7 | } 8 | 9 | provider "kubernetes" { 10 | host = data.aws_eks_cluster.cluster.endpoint 11 | cluster_ca_certificate = base64decode(data.aws_eks_cluster.cluster.certificate_authority.0.data) 12 | token = data.aws_eks_cluster_auth.cluster.token 13 | load_config_file = false 14 | version = "~> 1.9" 15 | } 16 | 17 | module "cluster" { 18 | source = "terraform-aws-modules/eks/aws" 19 | cluster_name = "demo-cluster" 20 | cluster_version = "1.17" 21 | subnets = var.subnets 22 | vpc_id = var.vpc_id 23 | 24 | worker_groups = [ 25 | { 26 | instance_type = "t2.medium" 27 | asg_max_size = 2 28 | } 29 | ] 30 | } 31 | 32 | locals { 33 | oidc_issuer = data.aws_eks_cluster.cluster.identity.0.oidc.0.issuer 34 | } 35 | 36 | data "tls_certificate" "cluster" { 37 | url = local.oidc_issuer 38 | } 39 | 40 | resource "aws_iam_openid_connect_provider" "cluster" { 41 | client_id_list = ["sts.amazonaws.com"] 42 | thumbprint_list = [data.tls_certificate.cluster.certificates.0.sha1_fingerprint] 43 | url = local.oidc_issuer 44 | } 45 | -------------------------------------------------------------------------------- /aws/eks/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | secrethub = { 4 | source = "secrethub/secrethub" 5 | version = "~> 1.2.3" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /aws/eks/variables.tf: -------------------------------------------------------------------------------- 1 | variable "secrethub_repo" { 2 | description = "SecretHub repo that contains the demo `username` and `password` secrets. To create this repo, run `secrethub demo init`." 3 | } 4 | 5 | variable "vpc_id" { 6 | description = "The VPC the EKS cluster lives in." 7 | } 8 | 9 | variable "subnets" { 10 | type = list(string) 11 | description = "The subnets the EKS cluster lives in. A minimum of 2 AZs is required." 12 | } 13 | -------------------------------------------------------------------------------- /ci/circleci/README.md: -------------------------------------------------------------------------------- 1 |

2 | CircleCI + SecretHub 3 |

4 |
5 | 6 |

7 | Learn More 8 | View Docs 9 |

10 |
11 | 12 |

13 | CircleCI Examples 14 |

15 | 16 | - [Publish Docker](./publish-docker/.circleci/config.yml) 17 | -------------------------------------------------------------------------------- /ci/circleci/publish-docker/.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | orbs: 3 | secrethub: secrethub/cli@1.1.0 4 | 5 | jobs: 6 | publish: 7 | docker: 8 | - image: cimg/base:stable 9 | environment: 10 | DOCKER_USERNAME: secrethub://company/app/docker/username 11 | DOCKER_PASSWORD: secrethub://company/app/docker/password 12 | steps: 13 | - checkout 14 | - setup_remote_docker 15 | - run: 16 | name: Build Docker image 17 | command: docker build -t company/app:${CIRCLE_SHA1:0:7} . 18 | - secrethub/exec: 19 | step-name: Publish Docker image 20 | command: | 21 | echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin 22 | docker push company/app:${CIRCLE_SHA1:0:7} 23 | workflows: 24 | deploy: 25 | jobs: 26 | - publish 27 | -------------------------------------------------------------------------------- /ci/circleci/publish-docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | 3 | CMD ["echo", "Hello World!"] 4 | -------------------------------------------------------------------------------- /ci/github-actions/publish-docker/.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | on: push 2 | jobs: 3 | publish: 4 | runs-on: ubuntu-latest 5 | steps: 6 | - uses: actions/checkout@v2 7 | - name: Build Docker image 8 | run: docker build -t company/app:${GITHUB_SHA:0:7} . 9 | - uses: secrethub/actions/env-export@v0.1.0 10 | env: 11 | SECRETHUB_CREDENTIAL: ${{ secrets.SECRETHUB_CREDENTIAL }} 12 | DOCKER_USERNAME: secrethub://company/app/docker/username 13 | DOCKER_PASSWORD: secrethub://company/app/docker/password 14 | - name: Publish Docker image 15 | run: | 16 | echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin 17 | docker push company/app:${GITHUB_SHA:0:7} 18 | -------------------------------------------------------------------------------- /ci/github-actions/publish-docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | 3 | CMD ["echo", "Hello World!"] 4 | -------------------------------------------------------------------------------- /ci/gitlab-ci/README.md: -------------------------------------------------------------------------------- 1 |

2 | GitLab CI + SecretHub 3 |

4 |
5 | 6 |

7 | View Docs 8 |

9 |
10 | 11 |

12 | GitLab CI Examples 13 |

14 | 15 | - [Publish Docker](./publish-docker/.gitlab-ci.yml) 16 | - [Deploy to AWS](./deploy-aws/.gitlab-ci.yml) 17 | -------------------------------------------------------------------------------- /ci/gitlab-ci/deploy-aws/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: amazon/aws-cli 2 | 3 | stages: 4 | - deploy 5 | 6 | deploy: 7 | stage: deploy 8 | variables: 9 | AWS_REGION: us-east-1 10 | AWS_ACCESS_KEY_ID: secrethub://company/app/aws/access_key_id 11 | AWS_SECRET_ACCESS_KEY: secrethub://company/app/aws/secret_access_key 12 | before_script: 13 | - apk add --repository https://alpine.secrethub.io/alpine/edge/main --allow-untrusted secrethub-cli 14 | script: 15 | - secrethub run -- ./deploy.sh 16 | -------------------------------------------------------------------------------- /ci/gitlab-ci/deploy-aws/deploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "containerDefinitions":[ 3 | { 4 | "name":"sleep", 5 | "image":"busybox", 6 | "cpu":10, 7 | "command":[ 8 | "sleep", 9 | "360" 10 | ], 11 | "memory":10, 12 | "essential":true 13 | } 14 | ], 15 | "family":"sleep360" 16 | } 17 | -------------------------------------------------------------------------------- /ci/gitlab-ci/deploy-aws/deploy.sh: -------------------------------------------------------------------------------- 1 | #!bin/bash 2 | export TASK_DEFINITION_ARN=$(aws ecs register-task-definition --family TestTaskDefinition --region $AWS_REGION --cli-input-json file://deploy.json | jq '.taskDefinition.taskDefinitionArn' --raw-output) 3 | aws ecs update-service --cluster testCluster --service testService --task-definition ${TASK_DEFINITION_ARN} --region $AWS_REGION 4 | -------------------------------------------------------------------------------- /ci/gitlab-ci/publish-docker/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - publish 3 | publish: 4 | stage: publish 5 | image: docker:19.03.1 6 | services: 7 | - docker:19.03.1-dind 8 | variables: 9 | DOCKER_TLS_CERTDIR: "/certs" 10 | DOCKER_USERNAME: secrethub://company/app/docker/username 11 | DOCKER_PASSWORD: secrethub://company/app/docker/password 12 | before_script: 13 | - apk add --repository https://alpine.secrethub.io/alpine/edge/main --allow-untrusted secrethub-cli 14 | script: 15 | - secrethub run -- sh -c 'echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin' 16 | - docker build -t company/app:${CI_COMMIT_SHA:0:7} . 17 | - docker push company/app:${CI_COMMIT_SHA:0:7} 18 | -------------------------------------------------------------------------------- /ci/gitlab-ci/publish-docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | 3 | CMD ["echo", "Hello World!"] 4 | -------------------------------------------------------------------------------- /devops-tools/terraform/README.md: -------------------------------------------------------------------------------- 1 | # Terraform Example 2 | This example creates a SecretHub service account in Terraform and grants it read access to a specified repository. 3 | 4 | ## Prerequisites 5 | 1. [Terraform](https://www.terraform.io/downloads.html) installed 6 | 2. [SecretHub](https://secrethub.io/docs/start/getting-started/#install) installed 7 | 8 | ## Running the example 9 | 10 | Initialize a terraform working directory by running: 11 | ``` 12 | terraform init 13 | ``` 14 | 15 | To create the service account, run: 16 | ``` 17 | terraform apply 18 | ``` 19 | and provide the requested information. 20 | 21 | The credential of the service account will be printed. 22 | 23 | > Note that the credential is only printed for demonstration purposes. 24 | > Service credentials must be kept secure and should not be logged. 25 | 26 | Moreover, a secret named `test` is also created in the specified repo. 27 | 28 | To verify that the service indeed has read access on repo, try reading the test secret with the service credential: 29 | ``` 30 | SECRETHUB_CREDENTIAL=$(terraform output service_credential) secrethub read $(terraform output secret_path) 31 | ``` 32 | -------------------------------------------------------------------------------- /devops-tools/terraform/main.tf: -------------------------------------------------------------------------------- 1 | resource "secrethub_service" "demo_service_account" { 2 | repo = "${var.secrethub_username}/${var.repo_name}" 3 | } 4 | 5 | resource "secrethub_access_rule" "demo_access_rule" { 6 | account_name = secrethub_service.demo_service_account.id 7 | dir = "${var.secrethub_username}/${var.repo_name}" 8 | permission = "read" 9 | } 10 | 11 | resource "secrethub_secret" "test_secret" { 12 | path = "${var.secrethub_username}/${var.repo_name}/test" 13 | 14 | generate { 15 | length = 22 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /devops-tools/terraform/output.tf: -------------------------------------------------------------------------------- 1 | output "service_credential" { 2 | value = secrethub_service.demo_service_account.credential 3 | sensitive = true 4 | } 5 | 6 | output "secret_path" { 7 | value = secrethub_secret.test_secret.path 8 | sensitive = false 9 | } 10 | -------------------------------------------------------------------------------- /devops-tools/terraform/variables.tf: -------------------------------------------------------------------------------- 1 | variable "secrethub_username" { 2 | description = "Your SecretHub username" 3 | } 4 | 5 | variable "repo_name" { 6 | description = "The name of the repo for which to create the service account" 7 | } 8 | -------------------------------------------------------------------------------- /google-cloud/gce/README.md: -------------------------------------------------------------------------------- 1 |

2 | GCE + SecretHub 3 |

4 |
5 | 6 |

7 | View Docs 8 |

9 |
10 | 11 | This example uses Terraform to launch an Google Compute instance, deploy the [SecretHub Demo App](https://secrethub.io/docs/start/getting-started/#consume) on it and provision it with the secrets it needs using the [SecretHub GCP Identity Provider](https://secrethub.io/docs/reference/gcp/). 12 | 13 | ## Prerequisites 14 | 1. [Terraform](https://www.terraform.io/downloads.html) installed along with the [SecretHub Provider](https://secrethub.io/docs/guides/terraform/#install) 15 | 1. Correctly configured [GCP Credentials](https://www.terraform.io/docs/providers/google/guides/provider_reference.html#full-reference) 16 | 1. [Values assigned](https://www.terraform.io/docs/configuration/variables.html#assigning-values-to-root-module-variables) to the variables in [variables.tf](./variables.tf) 17 | 18 | ## Running the example 19 | 20 | To launch a Compute instance (`n1-standard-1`) that runs the demo app, run: 21 | ``` 22 | terraform init 23 | terraform apply 24 | ``` 25 | 26 | Once the instance is running its public IP will be outputted. 27 | 28 | To see the app running, visit `http://:8080`. 29 | -------------------------------------------------------------------------------- /google-cloud/gce/app.tf: -------------------------------------------------------------------------------- 1 | resource "google_service_account" "demo_app" { 2 | account_id = "demo-app" 3 | description = "SecretHub demo app" 4 | } 5 | 6 | resource "google_kms_crypto_key" "demo_app" { 7 | name = "demo-app" 8 | key_ring = google_kms_key_ring.secrethub.id 9 | } 10 | 11 | resource "google_kms_crypto_key_iam_binding" "crypto_key" { 12 | crypto_key_id = google_kms_crypto_key.demo_app.id 13 | role = "roles/cloudkms.cryptoKeyDecrypter" 14 | 15 | members = [ 16 | "serviceAccount:${google_service_account.demo_app.email}", 17 | ] 18 | } 19 | 20 | resource "secrethub_service_gcp" "demo_app" { 21 | repo = var.secrethub_repo 22 | service_account_email = google_service_account.demo_app.email 23 | kms_key_id = google_kms_crypto_key.demo_app.id 24 | } 25 | 26 | resource "secrethub_access_rule" "demo_app" { 27 | account_name = secrethub_service_gcp.demo_app.id 28 | dir = var.secrethub_repo 29 | permission = "read" 30 | } 31 | 32 | resource "google_compute_instance" "demo_app" { 33 | name = "secrethub-demo" 34 | machine_type = "n1-standard-1" 35 | zone = var.gcp_zone 36 | 37 | boot_disk { 38 | initialize_params { 39 | // Image with Docker pre-installed 40 | image = "cos-cloud/cos-stable" 41 | } 42 | } 43 | 44 | network_interface { 45 | network = google_compute_firewall.demo_app.network 46 | 47 | access_config { 48 | // Auto-assign IP 49 | } 50 | } 51 | 52 | metadata_startup_script = < 2 | GKE + SecretHub 3 |

4 |
5 | 6 |

7 | View Docs 8 |

9 |
10 | 11 | This example uses Terraform to deploy the [SecretHub Demo App](https://secrethub.io/docs/start/getting-started/#consume) on a GKE cluster and provision it with the secrets it needs using the [SecretHub GCP Identity Provider](https://secrethub.io/docs/reference/gcp/). 12 | 13 | ## Prerequisites 14 | 1. [Terraform](https://www.terraform.io/downloads.html) installed along with the [SecretHub Provider](https://secrethub.io/docs/guides/terraform/#install) 15 | 1. Correctly configured [GCP Credentials](https://www.terraform.io/docs/providers/google/guides/provider_reference.html#full-reference) 16 | 1. [Values assigned](https://www.terraform.io/docs/configuration/variables.html#assigning-values-to-root-module-variables) to the variables in [variables.tf](./variables.tf) 17 | 18 | ## Running the example 19 | 20 | To deploy the app on your cluster, run: 21 | ``` 22 | terraform init 23 | terraform apply 24 | ``` 25 | 26 | After launching it, forward the port to your local machine using `kubectl`: 27 | 28 | ``` 29 | kubectl port-forward deployment/demo-app 8080 30 | ``` 31 | 32 | To see the app running, visit [http://127.0.0.1:8080](http://127.0.0.1:8080). 33 | -------------------------------------------------------------------------------- /google-cloud/gke/app.tf: -------------------------------------------------------------------------------- 1 | resource "google_service_account" "demo_app" { 2 | account_id = "demo-app" 3 | description = "SecretHub demo app" 4 | } 5 | 6 | resource "kubernetes_service_account" "demo_app" { 7 | metadata { 8 | name = "demo-app" 9 | 10 | annotations = { 11 | "iam.gke.io/gcp-service-account" = google_service_account.demo_app.email 12 | } 13 | } 14 | } 15 | 16 | resource "google_service_account_iam_binding" "demo_app" { 17 | service_account_id = google_service_account.demo_app.name 18 | role = "roles/iam.workloadIdentityUser" 19 | 20 | members = [ 21 | "serviceAccount:${var.gcp_project_id}.svc.id.goog[default/${kubernetes_service_account.demo_app.metadata[0].name}]", 22 | ] 23 | } 24 | 25 | resource "google_kms_crypto_key" "demo_app" { 26 | name = "demo-app" 27 | key_ring = google_kms_key_ring.secrethub.id 28 | } 29 | 30 | resource "google_kms_crypto_key_iam_binding" "crypto_key" { 31 | crypto_key_id = google_kms_crypto_key.demo_app.id 32 | role = "roles/cloudkms.cryptoKeyDecrypter" 33 | 34 | members = [ 35 | "serviceAccount:${google_service_account.demo_app.email}", 36 | ] 37 | } 38 | 39 | resource "secrethub_service_gcp" "demo_app" { 40 | repo = var.secrethub_repo 41 | service_account_email = google_service_account.demo_app.email 42 | kms_key_id = google_kms_crypto_key.demo_app.id 43 | } 44 | 45 | resource "secrethub_access_rule" "demo_app" { 46 | account_name = secrethub_service_gcp.demo_app.id 47 | dir = var.secrethub_repo 48 | permission = "read" 49 | } 50 | 51 | resource "kubernetes_deployment" "demo_app" { 52 | metadata { 53 | name = "demo-app" 54 | labels = { 55 | run = "demo-app" 56 | } 57 | } 58 | spec { 59 | replicas = 1 60 | selector { 61 | match_labels = { 62 | run = "demo-app" 63 | } 64 | } 65 | template { 66 | metadata { 67 | labels = { 68 | run = "demo-app" 69 | } 70 | } 71 | spec { 72 | service_account_name = kubernetes_service_account.demo_app.metadata[0].name 73 | 74 | container { 75 | image = "secrethub/demo-app" 76 | name = "demo-app" 77 | command = ["demo", "serve"] 78 | args = ["--host", "0.0.0.0", "--port", "8080"] 79 | port { 80 | container_port = 8080 81 | } 82 | env { 83 | name = "DEMO_USERNAME" 84 | value = "secrethub://${var.secrethub_repo}/username" 85 | } 86 | env { 87 | name = "DEMO_PASSWORD" 88 | value = "secrethub://${var.secrethub_repo}/password" 89 | } 90 | env { 91 | name = "SECRETHUB_IDENTITY_PROVIDER" 92 | value = "gcp" 93 | } 94 | } 95 | } 96 | } 97 | } 98 | 99 | wait_for_rollout = false 100 | depends_on = [ 101 | secrethub_access_rule.demo_app, 102 | ] 103 | } 104 | -------------------------------------------------------------------------------- /google-cloud/gke/main.tf: -------------------------------------------------------------------------------- 1 | provider "google" { 2 | project = var.gcp_project_id 3 | } 4 | 5 | data "google_client_config" "provider" {} 6 | 7 | data "google_container_cluster" "cluster" { 8 | name = var.gke_cluster 9 | location = var.gke_cluster_location 10 | } 11 | 12 | provider "kubernetes" { 13 | load_config_file = false 14 | host = "https://${data.google_container_cluster.cluster.endpoint}" 15 | token = data.google_client_config.provider.access_token 16 | cluster_ca_certificate = base64decode(data.google_container_cluster.cluster.master_auth[0].cluster_ca_certificate) 17 | } 18 | 19 | terraform { 20 | required_providers { 21 | secrethub = { 22 | source = "secrethub/secrethub" 23 | version = "~> 1.2.3" 24 | } 25 | } 26 | } 27 | 28 | resource "google_kms_key_ring" "secrethub" { 29 | name = "secrethub" 30 | location = "global" 31 | } 32 | -------------------------------------------------------------------------------- /google-cloud/gke/variables.tf: -------------------------------------------------------------------------------- 1 | variable "gcp_project_id" { 2 | description = "GCP project ID." 3 | } 4 | 5 | variable "gke_cluster" { 6 | description = "Name of your GKE cluster, must be in `gcp_location`." 7 | } 8 | 9 | variable "gke_cluster_location" { 10 | description = "GCP location where the `gke_cluster` runs." 11 | } 12 | 13 | variable "secrethub_repo" { 14 | description = "SecretHub repo that contains the demo `username` and `password` secrets. To create the repo, run `secrethub demo init`." 15 | } 16 | --------------------------------------------------------------------------------