How to retrieve secrets from CredHub in the config server
search cancel

How to retrieve secrets from CredHub in the config server

book

Article ID: 297117

calendar_today

Updated On:

Products

Support Only for Spring

Issue/Introduction

The Spring Cloud Services (SCS) Config Server provides the ability to serve configuration properties from a composite of multiple backends, such as from multiple Git repositories, a HashiCorp Vault server and the runtime CredHub within VMware Tanzu Application Service for VMs (TAS) for secrets. If both Credhub and Git/Vault are specified as composite backends, the Credhub has the precedence.

Secrets stored by one Config Server service instance are accessible only to that service instance, and a given Config Server service instance can add, serve, or delete only its own secrets in the runtime CredHub. This Knowledge Base (KB) article describes how the app can retrieve the secrets.

Resolution

From a high level, the app fetches properties from the config server just like it does with Git/Vault backend. In a Spring Cloud app, you can use @Value Spring annotation for injecting values into fields in Spring-managed beans and it can be applied at the field or the constructor/method parameter level.

For example, If you create the following secret:
curl -i -H "Content-Type: application/json" -H "Authorization: $(cf oauth-token)" https://config-server-1aba3979-4e41-479a-a8a1-de01108155e1.<DOMAIN>/secrets/config-server-demo/development/master/mysecret -X PUT --data '{"mysecret": "xxxxxx"}'

It can be injected into a string variable, mysecret with the following command:
package com.example.configserverdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Value;

@SpringBootApplication
@RestController
public class ConfigServerDemoApplication {
    @Value("${mysecret}")
    String mysecret;

    public static void main(String[] args) {
        SpringApplication.run(ConfigServerDemoApplication.class, args);
    }

    @RequestMapping("/")
    public String home() {    
        return "mysecret from config server is: " + mysecret;
    }
}


The application profile should be as same as [PROFILE_NAME] in path [APP_NAME]/[PROFILE_NAME]/[LABEL_NAME]/[SECRET_NAME]. In this example, SPRING_PROFILES_ACTIVE is configured as development.

---
applications:
- name: config-server-demo
  instances: 1
  memory: 1024M
  buildpack: java_buildpack_offline  
  path: target/config-server-demo-0.0.1-SNAPSHOT.jar
  services:
  - config-server  
  env:
    SPRING_PROFILES_ACTIVE: development


Application dependency (pom.yml) can be specified as the following:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example</groupId>
	<artifactId>config-server-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>config-server-demo</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.10.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<spring-cloud-services.version>1.6.1.RELEASE</spring-cloud-services.version>
		<spring-cloud.version>Edgware.SR2</spring-cloud.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>io.pivotal.spring.cloud</groupId>
			<artifactId>spring-cloud-services-starter-config-client</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency> 
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>io.pivotal.spring.cloud</groupId>
				<artifactId>spring-cloud-services-dependencies</artifactId>
				<version>${spring-cloud-services.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

Note: The entire source code is attached as config-server-demo-master.zip.

Attachments

config-server-demo-master get_app