skip to content

How do you produce a {cipher} value for the config repo using the Config Server's /encrypt and /decrypt endpoints?

level: middleimportance: should knowfreq 45%

answer

  1. POST /encrypt -> ciphertext; POST /decrypt -> plaintext
  2. body is raw text/plain (watch trailing newline)
  3. only on server, only when key configured
  4. no key -> 404
  5. unauthenticated by default -> MUST secure /decrypt

basics

~10 s

POST the plaintext to the Config Server's /encrypt endpoint; it returns ciphertext. You paste that into the repo prefixed with {cipher}. POST ciphertext to /decrypt to reverse it. Both need a configured key.

solid answer

~40 s

The Config Server auto-exposes two POST endpoints, /encrypt and /decrypt, once an encryption key is configured. You send the raw secret as the request body (text/plain) to /encrypt and it returns the ciphertext blob; you store it in the repo as '{cipher}<blob>'. /decrypt does the reverse and is mainly for verification. Example: curl localhost:8888/encrypt -d 'mysecret'. These endpoints live only on the Config Server, not on clients. They are unauthenticated by default, so in any real environment you must secure them (Spring Security, network isolation) — otherwise anyone can decrypt your secrets. If no key is set, the endpoints return 404. Note the request body is the exact plaintext; be careful with trailing newlines (use curl --data-binary or -d without a file) since they become part of the encrypted value.

code

java · 19 lines
java
// Config Server bootstrap: enable it and configure a key so /encrypt & /decrypt appear.
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

/*
application.yml (server):
  encrypt:
    key: ${ENCRYPT_KEY}   # symmetric key, injected from env, never committed

Then:
  curl -s http://localhost:8888/encrypt -d 'p@ssw0rd'   -> AQBc9f2h...==
  curl -s http://localhost:8888/decrypt -d 'AQBc9f2h...==' -> p@ssw0rd
Store in repo:  my.password: '{cipher}AQBc9f2h...=='
*/

go deeper

for a junior

Know /encrypt gives you the blob you paste after {cipher}.

for a middle

Explain the full round-trip, text/plain body, and 404-without-key behavior.

for a senior

Stress securing/disabling /decrypt and the trailing-newline pitfall; mention the Spring Cloud CLI alternative.

for a principal

Design an operational model where encryption happens on a locked-down instance or CLI and public endpoints are off entirely.

**What the endpoints are.** When a Spring Cloud **Config Server** has an encryption key configured, it automatically registers two HTTP endpoints implemented by `EncryptionController`: - `POST /encrypt` — body = plaintext, response = ciphertext (to be stored as `{cipher}<ciphertext>`). - `POST /decrypt` — body = ciphertext (without the `{cipher}` prefix), response = the original plaintext. Used mainly to verify a value or for the client-side model. **Typical workflow.** ```bash # 1. Encrypt a secret $ curl -s http://localhost:8888/encrypt -d 'p@ssw0rd' AQBc9f2hXk1o...== # 2. Put it in the repo, prefixed: # my.password: '{cipher}AQBc9f2hXk1o...==' # 3. (Optional) verify $ curl -s http://localhost:8888/decrypt -d 'AQBc9f2hXk1o...==' p@ssw0rd ``` **Content type and body.** Send the value as the raw request body with `Content-Type: text/plain`. The **entire body** is treated as the plaintext, so a stray trailing newline (common when piping a file) becomes part of the secret. Prefer `-d 'value'` or `--data-binary` and avoid `@file` with a newline, or you'll decrypt to `value\n`. **Path/name context.** You can encrypt in the context of an app/profile using `/encrypt/{name}/{profiles}` — with RSA and `salt`/`strong` settings, some configurations bind the ciphertext to a name so it can only be decrypted for that application, adding defense in depth. **Availability.** These endpoints exist **only on the Config Server** and only when a key is present; with no key configured a `/encrypt` call returns **404 Not Found** (endpoint effectively disabled). They are **not** exposed on client applications. **Security — the big gotcha.** By default `/encrypt` and especially `/decrypt` are **unauthenticated**. An exposed `/decrypt` lets anyone turn your repo ciphertext back into plaintext, defeating the whole scheme. You must protect the Config Server: add Spring Security (HTTP Basic / OAuth2), restrict `/decrypt` or disable it, and/or keep the server on a private network. Many teams encrypt with a CLI or a locked-down admin instance and never expose these endpoints publicly. **Spring Cloud CLI alternative.** The Spring Cloud CLI offers `spring encrypt`/`spring decrypt` to do this locally without a running server, avoiding network exposure. **When to use.** Use `/encrypt` to mint values at development/deploy time; treat `/decrypt` as a verification/debug tool that should be locked down or off in production.

  • Why is leaving /decrypt publicly reachable dangerous even if /encrypt seems harmless?
    /decrypt turns any repo ciphertext back into plaintext without a key, so an attacker with repo read access plus an open /decrypt recovers every secret. It must be authenticated, restricted, or disabled in production.
  • You piped a file into /encrypt and the decrypted value has a trailing newline. What happened and how do you avoid it?
    The endpoint treats the entire request body as plaintext, so the file's trailing newline was encrypted too. Use curl -d 'value' or --data-binary without the newline, or printf without \n.

saying these in an interview costs you the question

  • Thinking /encrypt and /decrypt live on the client apps
  • Assuming the endpoints are secure by default
  • Forgetting the {cipher} prefix is added by hand, not returned by /encrypt

context