///////////////////////////////////////////////////////////////////////////////

    Copyright (c) 2018,2019 Oracle and/or its affiliates. All rights reserved.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

///////////////////////////////////////////////////////////////////////////////

= Configuration Secrets
:description: Helidon MicroProfile configuration secrets
:keywords: helidon, microprofile, micro-profile

When security requires a configuration with repeating complex elements, use Helidon
 Config. 
 
This example configures a basic authentication provider and
 protects static content on the web server. It also includes annotations in Jersey.

== Protecting Static Content

[source,yaml]
.application.yaml
----
security:
  providers:
    # Attribute based access control, validates roles
    - abac:
    # HTTP Basic authentication provider
    - http-basic-auth:
        realm: "helidon"
        users:
          - login: "jack"
            password: "password"
            roles: ["user", "admin"]
          - login: "jill"
            password: "password"
            roles: ["user"]
          - login: "john"
            password: "password"
  # Protect static content - require authenticated user
  web-server:
    paths:
      - path: "/static-cp[/{*}]"
        authenticate: true
----

=== Protecting Configuration Secrets 

In Helidon MP, the config encryption filter ** enabled by default**. However, if you don't configure it, the filter
 only supports a template for aliasing that checks that no clear text passwords are
 present (template ${CLEAR=...}.

In Helidon SE, you may add support for this filter with dependency (loaded through a java service mechanism):

[source,xml]
.Maven Dependency
----
<dependency>
    <groupId>io.helidon.config</groupId>
    <artifactId>helidon-config-encryption</artifactId>
</dependency>
----

Put encrypted values into your
 configuration file so that it can be stored in a public repository with no danger of
 exposing the secret values. Be sure to use a strong and secret password.

The supported templates are:

.Templates
[cols="1,3,5"]
|===
|Template |Description |Example

|${CLEAR=...}
|Secret in clear text (for testing) - `requiresEncryption` must be disabled
|${CLEAR=knownSecret}

|${RSA=...}
|Public/private key encryption, base64 value
|${RSA=aGr3sFCMQznixrgbIk9qNfoLnO1cdi3H86qweCNjxFvH4dYg5IQM1EuoyTjJaXcSCG5MBskpeA3bjnWYrzeAFFlZHuYSPsb+wJVzGLrfUColTn+BPJjpJ3rmEd3AVkJl1ASfBBMh3q3deC+rvUdhfoTGBO8sC0teUATklCQSxfHOnIxswxqrplnoGXToGiTIfehiN2IZNulRKeoDQ0AeoKREmq5au4L8OOmS+D9BqnlKMc0F1tULZ7+h3Cxla4lXC5WRPoPfHBU4vzRZOGzeDvLkRgrD60caw/wKn5M0Wy1A1cKR8E46ceBXCjJ2eWIcLyhZSAZWDe3ceNrawHZtCg==}

|${AES=...}
|Shared secret ecryption, base64 value
|${AES=D/UgMzsNb265HU1NDvdzm7tACHdsW6u1PjYEcRkV/OLiWcI+ET6Q4MKCz0zHyEh9}

|${ALIAS=...}
|Reference to another key
|${ALIAS=someOtherKey}
|===

=== Requiring encryption 

The config encryption filter has an option that defines whether
encryption is required or not. If it's set to true, which is the default, then:
 
* Configuration values with ${CLEAR=...} template will cause an exception when
 requested.
* The filter fails during bootstrap if `security.config.aes.insecure-passphrase`
 is configured.

=== Using symmetric encryption (AES)
Symmetric encryption is based on a shared secret that is known by the person
encrypting the value and is also provided to the application.

==== Encrypting values (AES)

The config encryption filter provides a Main class `io.helidon.config.encryption.Main`
 that can be used to encrypt values.

[source,bash]
.Encrypt secret `secretToEncrypt` using shared secret `masterPassword`
----
java io.helidon.config.encryption.Main aes masterPassword secretToEncrypt
----

The tool returns the string to be entered into configuration as the value of a
 property.

==== Shared Secret (AES)

You can provide a shared secret in a couple of ways:

- in configuration - for testing/demo purposes only - key is
 `security.config.aes.insecure-passphrase`
- as an environment variable - `SECURE_CONFIG_AES_MASTER_PWD`

=== Using asymmetric encryption (RSA)
This approach is based on a pair of keys: a public key which is known to anybody, and a
 private key which is known to a limited set of parties (usually a single person or
 process). 
 For asymmetric encryption, the following is true:

- a value encrypted by a public key can only be decrypted by the private key
- a value encrypted by a private key can only be decrypted by the public key

When using the config encryption filter, you should encrypt the configuration values
using the public key, and give the application process access to the 
private key to decrypt the values.

==== Encrypting values (RSA)
The config encryption filter provides a Main class `io.helidon.config.encryption.Main`
 that can be used to encrypt values.

[source,bash]
.Encrypt secret `secretToEncrypt` using public certificate in a keystore
----
java io.helidon.config.encryption Main rsa /path/to/keystore.p12 keystorePassword publicCertAlias secretToEncrypt
----

The tool returns the string to be entered into configuration as the value of a
 property.

==== Configure config encryption filter (RSA)

You can configure the properties of a private key. These
 keys are prefixed with `security.config.rsa`


.RSA Configuration Options: Keystore
[cols="2,2,3,5"]
|===
|What |Configuration Key |Environment Variable|Description

|Keystore path
|`keystore-path`
|`SECURE_CONFIG_RSA_PRIVATE_KEY`
|Keystore is located in file system

|Keystore
|`keystore-resource-path`
|N/A
|Keystore is located on classpath

|Private key alias
|`key-alias`
|`SECURE_CONFIG_PRIVATE_KEY_ALIAS`
|Alias of the private key (such as "1", which is usually the default)

|Keystore passphrase
|`keystore-passphrase`
|`SECURE_CONFIG_PRIVATE_KEYSTORE_PASSPHRASE`
|Password for the keystore (and private key).
|===

.RSA Configuration Options: PEM (PKCS#8) private key
[cols="2,2,3,5"]
|===
|What |Configuration Key |Environment Variable|Description

|Path
|`pem-key-path`
|`SECURE_CONFIG_RSA_PEM_KEY`
|Key is located on file system

|Resource path
|`pem-key-resource-path`
|N/A
|Key is located on classpath

|Passphrase
|`pem-key-passphrase`
|`SECURE_CONFIG_PRIVATE_KEY_PASSPHRASE`
|Password protecting the private key
|===

[source,yaml]
.Example yaml configuration
----
security.config:
  # Set to true for production - if set to true, clear text passwords will cause failure
  require-encryption: false
  # The "master" password for AES decryption. For production, set this via system property or environment variable.
  aes.insecure-passphrase: "myMasterPasswordForEncryption"
  # See documentation of pki-util
  rsa:
    # load from classpath
    keystore-resource-path: ".ssh/keystore.p12"
    # If keystore is used, alias to use from the keystore (in this example, it is "1")
    key-alias: "1"
    # Password of keystore
    keystore-passphrase: "helidon"
----
