|
| 1 | +--- |
| 2 | +layout: page |
| 3 | +title: By Application Type |
| 4 | +parent: Practical use cases |
| 5 | +--- |
| 6 | + |
| 7 | +# 1. Other maven plugins |
| 8 | +Many CI tools are used via maven plugins for the convenience of not having to manage executables. |
| 9 | +Sonar scanner and liquibase are one of them. |
| 10 | +The example below shows you how to fetch the credentials necessary to use those plugins, via the vault-maven-plugin. |
| 11 | + |
| 12 | +Let's say you are using liquibase and have the following pom.xml |
| 13 | +```xml |
| 14 | +<build> |
| 15 | + <plugins> |
| 16 | + <plugin> |
| 17 | + <groupId>org.liquibase</groupId> |
| 18 | + <artifactId>liquibase-maven-plugin</artifactId> |
| 19 | + <version>4.6.1</version> |
| 20 | + <executions> |
| 21 | + <execution> |
| 22 | + <phase>compile</phase> |
| 23 | + <goals> |
| 24 | + <goal>update</goal> |
| 25 | + </goals> |
| 26 | + </execution> |
| 27 | + </executions> |
| 28 | + <configuration> |
| 29 | + <propertyFile>target/classes/liquibase.properties</propertyFile> |
| 30 | + </configuration> |
| 31 | + </plugin> |
| 32 | + </plugins> |
| 33 | + <resources> |
| 34 | + <resource> |
| 35 | + <directory>src/main/resources</directory> |
| 36 | + <filtering>true</filtering> |
| 37 | + <includes> |
| 38 | + <include>*.properties</include> |
| 39 | + </includes> |
| 40 | + </resource> |
| 41 | + </resources> |
| 42 | +</build> |
| 43 | +``` |
| 44 | + |
| 45 | +Your property file might be like below. |
| 46 | +```properties |
| 47 | +changeLogFile=src/main/resources/liquibase/.../changelog.xml |
| 48 | +url=... |
| 49 | +database=... |
| 50 | +username=... |
| 51 | +password=${database.password} |
| 52 | +``` |
| 53 | + |
| 54 | +Usually the property `database.password` if given to maven as system property or environment variables. |
| 55 | + |
| 56 | +If you don't have a tool that will fetch the secret and create the environment variable for you, you can use the maven vault plugin. |
| 57 | +You just add the following to fetch the secrets and inject them as properties in maven. |
| 58 | +```xml |
| 59 | +<plugin> |
| 60 | + <groupId>com.homeofthewizard</groupId> |
| 61 | + <artifactId>vault-maven-plugin</artifactId> |
| 62 | + <version>1.1.2-SNAPSHOT</version> |
| 63 | + <executions> |
| 64 | + <execution> |
| 65 | + <id>pull</id> |
| 66 | + <phase>initialize</phase> |
| 67 | + <goals> |
| 68 | + <goal>pull</goal> |
| 69 | + </goals> |
| 70 | + </execution> |
| 71 | + </executions> |
| 72 | + <configuration> |
| 73 | + <servers> |
| 74 | + <server> |
| 75 | + <url>https://your-vault-host</url> |
| 76 | + <token>XXXXXXX</token> |
| 77 | + <paths> |
| 78 | + <path> |
| 79 | + <name>secret/data/some-app</name> |
| 80 | + <mappings> |
| 81 | + <mapping> |
| 82 | + <key>vaultSecretKey</key> |
| 83 | + <property>database.password</property> |
| 84 | + </mapping> |
| 85 | + </mappings> |
| 86 | + </path> |
| 87 | + </paths> |
| 88 | + </server> |
| 89 | + </servers> |
| 90 | + </configuration> |
| 91 | +</plugin> |
| 92 | +``` |
| 93 | + |
| 94 | +and Voilà! :tada: |
| 95 | +When you execute your liquibase plugin `mvn clean compile`, |
| 96 | +the vault plugin will fetch the secrets, |
| 97 | +the resource plugin will put it in the property file by replacing the placeholder, |
| 98 | +then the liquibase plugin will run using the secret! |
| 99 | + |
| 100 | +No need to handle secrets in the execution environment anymore ! :massage_man: |
| 101 | +You only need to give set the execution environment's credentials to access Vault! |
| 102 | + |
| 103 | +# 2. Maven Applications |
| 104 | + |
| 105 | +{: .warning } |
| 106 | +As already mentionned [here](https://homeofthewizard.github.io/vault-maven-plugin/#example-use-cases), if your application is using Spring-Cloud, |
| 107 | +You should use [Spring Cloud Vault](https://spring.io/projects/spring-cloud-vault) instead of this maven plugin. |
| 108 | + |
| 109 | +Many Java application like Spring applications externalise their configurations in a property file, |
| 110 | +as recommended by the [12 factor app](https://12factor.net/config). |
| 111 | +Secrets are part of those configuration files. The configuration file can be stored in version control. |
| 112 | +But a good security practice is not to store the secrets on version control. |
| 113 | +Hence, the secrets are fetched generally from environment variables on the system where we run the app. |
| 114 | + |
| 115 | +You can do the following to fetch the secrets from vault via the Vault Plugin, |
| 116 | +then run your application with maven, and your secrets will be injected as system properties. |
| 117 | + |
| 118 | +Let's say you are using Spring and have the following `application.properties` |
| 119 | +```properties |
| 120 | +app.secret=${APPLICATION_SECRET} |
| 121 | +``` |
| 122 | + |
| 123 | +You can define the following in your pom.xml to fetch the credential for `APPLICATION_SECRET`. |
| 124 | +```xml |
| 125 | +<plugins> |
| 126 | + <plugin> |
| 127 | + <groupId>com.homeofthewizard</groupId> |
| 128 | + <artifactId>vault-maven-plugin</artifactId> |
| 129 | + <version>1.1.2-SNAPSHOT</version> |
| 130 | + <executions> |
| 131 | + <execution> |
| 132 | + <id>pull</id> |
| 133 | + <phase>initialize</phase> |
| 134 | + <goals> |
| 135 | + <goal>pull</goal> |
| 136 | + </goals> |
| 137 | + </execution> |
| 138 | + </executions> |
| 139 | + <configuration> |
| 140 | + <servers> |
| 141 | + <server> |
| 142 | + <url>https://your-vault-host</url> |
| 143 | + <token>XXXXXXX</token> |
| 144 | + <paths> |
| 145 | + <path> |
| 146 | + <name>secret/data/some-app</name> |
| 147 | + <mappings> |
| 148 | + <mapping> |
| 149 | + <key>vaultSecretKey</key> |
| 150 | + <property>APPLICATION_SECRET</property> |
| 151 | + </mapping> |
| 152 | + </mappings> |
| 153 | + </path> |
| 154 | + </paths> |
| 155 | + </server> |
| 156 | + </servers> |
| 157 | + <outputMethod>SystemProperties</outputMethod> |
| 158 | + </configuration> |
| 159 | + </plugin> |
| 160 | +</plugins> |
| 161 | +``` |
| 162 | + |
| 163 | +The above code will first fetch the secrets from vault with the vault-plugin, then they will be added to Maven's system properties (`<outputMethod>` configuration). |
| 164 | +After that you can run your java app with either [exec-maven-plugin](http://www.mojohaus.org/exec-maven-plugin/usage.html) or the [spring-boot-maven-plugin](https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/) |
| 165 | +By running your application with maven, maven's system properties will be shared with your application. |
| 166 | + |
| 167 | +<p><img src="../assets/images/old%20vs%20new%20way.png"/></p> |
| 168 | + |
| 169 | +### In case you have a Non-Spring Java application |
| 170 | +Spring boot manages system properties and environment variables differently that the standard way. |
| 171 | +You will find here a [blog post](https://homeofthewizard.github.io/secrets-in-java) that explains how the two works in java, and [here](https://www.baeldung.com/spring-boot-properties-env-variables) a post explaining spring's difference. |
| 172 | +But in short, Spring allows you to access both via the same API (using placeholders like `${myVar}`). So for a spring application that requires environment variables, we can emulate them by injecting System properties instead. |
| 173 | + |
| 174 | +For a non Spring application that requires environment variables, we cannot do that, we need to give the JVM real environment variables. |
| 175 | +Let's say you have a simple java application, with a main class like this |
| 176 | +```java |
| 177 | +package org.example; |
| 178 | + |
| 179 | +public class Main { |
| 180 | + public static void main(String[] args) { |
| 181 | + System.out.println("Env variable fetched: "+ System.getenv("ENV_VAR_SECRET")); |
| 182 | + } |
| 183 | +} |
| 184 | +``` |
| 185 | + |
| 186 | +you have the following pom.xml |
| 187 | +```xml |
| 188 | +<plugins> |
| 189 | + <plugin> |
| 190 | + <groupId>org.apache.maven.plugins</groupId> |
| 191 | + <artifactId>maven-jar-plugin</artifactId> |
| 192 | + <configuration> |
| 193 | + <archive> |
| 194 | + <manifest> |
| 195 | + <addClasspath>true</addClasspath> |
| 196 | + <mainClass>org.example.Main</mainClass> |
| 197 | + </manifest> |
| 198 | + </archive> |
| 199 | + </configuration> |
| 200 | + </plugin> |
| 201 | +</plugins> |
| 202 | +``` |
| 203 | + |
| 204 | +This app is using some environment variables given by its execution environment |
| 205 | +when run via `java -jar myApp.jar`. |
| 206 | + |
| 207 | +Now if we use the Vault Maven Plugin, we can fetch the secret, run the app via maven, and the env variable will be injected directly. |
| 208 | +By adding the followings to your pom.xml like so: |
| 209 | +```xml |
| 210 | +<plugins> |
| 211 | + <plugin> |
| 212 | + <groupId>org.apache.maven.plugins</groupId> |
| 213 | + <artifactId>maven-jar-plugin</artifactId> |
| 214 | + <configuration> |
| 215 | + <archive> |
| 216 | + <manifest> |
| 217 | + <addClasspath>true</addClasspath> |
| 218 | + <mainClass>org.example.Main</mainClass> |
| 219 | + </manifest> |
| 220 | + </archive> |
| 221 | + </configuration> |
| 222 | + </plugin> |
| 223 | + <plugin> |
| 224 | + <groupId>com.homeofthewizard</groupId> |
| 225 | + <artifactId>vault-maven-plugin</artifactId> |
| 226 | + <version>1.1.2-SNAPSHOT</version> |
| 227 | + <executions> |
| 228 | + <execution> |
| 229 | + <id>pull</id> |
| 230 | + <phase>initialize</phase> |
| 231 | + <goals> |
| 232 | + <goal>pull</goal> |
| 233 | + </goals> |
| 234 | + </execution> |
| 235 | + </executions> |
| 236 | + <configuration> |
| 237 | + <servers> |
| 238 | + <server> |
| 239 | + <url>https://your-vault-host</url> |
| 240 | + <token>XXXXX</token> |
| 241 | + <paths> |
| 242 | + <path> |
| 243 | + <name>secret/data/myJavaApp</name> |
| 244 | + <mappings> |
| 245 | + <mapping> |
| 246 | + <key>secretKey</key> |
| 247 | + <property>mavenPropertyForSecret</property> |
| 248 | + </mapping> |
| 249 | + </mappings> |
| 250 | + </path> |
| 251 | + </paths> |
| 252 | + </server> |
| 253 | + </servers> |
| 254 | + </configuration> |
| 255 | + </plugin> |
| 256 | + <plugin> |
| 257 | + <groupId>org.codehaus.mojo</groupId> |
| 258 | + <artifactId>exec-maven-plugin</artifactId> |
| 259 | + <version>1.2.1</version> |
| 260 | + <configuration> |
| 261 | + <executable>java</executable> |
| 262 | + <environmentVariables> |
| 263 | + <ENV_VAR_SECRET>${mavenPropertyForSecret}</ENV_VAR_SECRET> |
| 264 | + </environmentVariables> |
| 265 | + <arguments> |
| 266 | + <argument>-classpath</argument> |
| 267 | + <classpath /> |
| 268 | + <argument>org.example.Main</argument> |
| 269 | + </arguments> |
| 270 | + </configuration> |
| 271 | + </plugin> |
| 272 | +</plugins> |
| 273 | +``` |
| 274 | +And Voilà! :tada: |
| 275 | +Now you just need to run `mvn vault:pull exec:exec` |
| 276 | +The only thing to provide is the token to authenticate to Vault server (`<token>XXXXX</token>`). |
| 277 | +Isn't that magical ? :mage: |
| 278 | + |
| 279 | +# 3. Application that does not use Maven |
| 280 | +Many developers use .env files to manage environment variables on their localhost. |
| 281 | +It may be the case even on production for application that do not have tools to fetch the secrets directly from a secure shared place like Vault. |
| 282 | + |
| 283 | +If that is the case, the plugin can generate a .env file for you. |
| 284 | +The configuration `<outputMethod>EnvFile</outputMethod>` allows this. |
| 285 | + |
| 286 | +Then you can inject it with [dotenv-java](https://github.com/cdimascio/dotenv-java) for example. |
| 287 | + |
| 288 | +There are also IntelliJ plugins that help you inject secrets via .env files before running/debugging the application in your local environment. |
0 commit comments