简体   繁体   中英

Reading an env variable in Spring

I need to read a private key from an env variable in kubernetes. To try that my code works I'm reading it now from the resource folder so everytime I'm running my app locally it can be read from it. The thing is now I've deployed my app and created a secret with this private key in kubernetes.

I've also created a test endpoint to check that my env variable is in kubernetes:

@GetMapping("/test")
    public ResponseEntity test() {
        return ResponseEntity.ok(System.getenv());
    }

After checking that it has been set, I've written this code in order to read that private key, it the app is running locally, from the resource folder but if it's runnign on dev, it has to be read from that env variable. The thing is that this is not working when deployed to PaaS but it is read when trying locally. Here's the code to achieve that:

@Configuration
@RequiredArgsConstructor
public class JwtKeyProviderConfig {

    private final static String PRIVATE_KEY_ENVIRONMENT_VARIABLE_NAME = "PRIVATE_KEY";
    private final static String LOCAL_ENVIRONMENT_NAME = "local";
    private final static String TEST_ENVIRONMENT_NAME = "test";
    private final static String DEVELOPMENT_ENVIRONMENT_NAME = "development";

    private final static String LOCAL_PRIVATE_KEY_RESOURCE_PATH = "classpath:keys/private_key.pkcs8";

    private final ResourceUtil resourceUtil;
    private final Base64Util base64Util;
    private final Environment environment;

    @Bean
    public PrivateKey getPrivateKeyFromEnvironmentVariable() throws IOException {
        List<String> activeProfiles = Arrays.asList(environment.getActiveProfiles());
        boolean isLocalOrTestEnvironment = activeProfiles.contains(LOCAL_ENVIRONMENT_NAME) || activeProfiles.contains(DEVELOPMENT_ENVIRONMENT_NAME);

        //TODO It's not reading from the ENV in openshift, it was reading it from the private key uploaded in git
        String key = isLocalOrTestEnvironment ? resourceUtil.asString(LOCAL_PRIVATE_KEY_RESOURCE_PATH) : System.getenv(PRIVATE_KEY_ENVIRONMENT_VARIABLE_NAME);
        return readKey(
                key,
                "PRIVATE",
                this::privateKeySpec,
                this::privateKeyGenerator
        );
    }

    private <T extends Key> T readKey(String keyString, String headerSpec, Function<String, EncodedKeySpec> keySpec, BiFunction<KeyFactory, EncodedKeySpec, T> keyGenerator) {
        try {
            //TODO you can check the headers and throw an exception here if you want

            keyString = keyString
                    .replace("-----BEGIN " + headerSpec + " KEY-----", "")
                    .replace("-----END " + headerSpec + " KEY-----", "")
                    .replaceAll("\\s+", "");

            return keyGenerator.apply(KeyFactory.getInstance("RSA"), keySpec.apply(keyString));
        } catch(NoSuchAlgorithmException e) {
            throw new JwtInitializationException(e);
        }
    }

    private EncodedKeySpec privateKeySpec(String data) {
        return new PKCS8EncodedKeySpec(base64Util.decode(data));
    }

    private PrivateKey privateKeyGenerator(KeyFactory kf, EncodedKeySpec spec) {
        try {
            return kf.generatePrivate(spec);
        } catch(InvalidKeySpecException e) {
            throw new JwtInitializationException(e);
        }
    }

}

Any idea why it's not working on remote? Thanks in advance

Why so complicated?

You can read environment variable with Spring like all configuration values with @Value

@Value("${PRIVATE_KEY}")
private String privateKey;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM