×
Community Blog Best Practice for Using KMS to Encrypt Sensitive Configurations in the Apollo Configuration Center

Best Practice for Using KMS to Encrypt Sensitive Configurations in the Apollo Configuration Center

This article describes the best practice for using Key Management Service (KMS) to encrypt sensitive configurations in the Apollo configuration center.

By Yong Yang

1. Security Challenges to Sensitive Data in Apollo

Many users increasingly store sensitive data in Apollo, such as data sources, tokens, usernames, and passwords, when using Apollo to manage configurations. First, user-built Apollo instances lack security protection and are vulnerable to attacks. Second, sensitive information stored in plaintext is easily stolen, which poses significant risks to the company's information security. Multi-Level Protection Scheme (MLPS) Level 3 is a scheme that aims to protect important information systems. It has the following requirements for application and data security:

• Secure coding principles should be followed in the software development process to reduce potential vulnerabilities.

• Data should be encrypted as necessary during storage and processing, and data integrity check mechanisms should also be set up.

• After sensitive data, such as AccessKey IDs, is compromised, its plaintext is easily obtained and can be directly exploited.

2. Product Architecture

KMS provides an integrated solution for encrypting and decrypting sensitive configurations in Apollo. In this solution, KMS encrypts and decrypts sensitive configurations and Apollo stores the encrypted configurations. The following figure shows the overall product logic architecture.

1

3. Use Apollo and KMS 3.0 in the Best Practice

This section describes how to use the configuration encryption capability provided by Apollo.

The entire best practice mainly includes the following steps:

• Self-build and activate Apollo.

• Activate KMS.

• Log on to the KMS console, create a dedicated KMS instance, and create a key.

• Configure the KMS SDK in Apollo for encryption configuration.

3.1. Activate MSE

Install Docker and Docker Compose.

Download the docker-compose.yml, apolloconfigdb.sql, and apolloportaldb.sql files.

2

3.2. Start the Apollo Configuration Center

3

3.3. Visit the Apollo Configuration Center

Default account: [apollo/admin]

4

3.4. Create, Update, Delete, and Get Apollo Configuration Items with Apollo Admin APIs

For more information, visit https://www.apolloconfig.com/#/en/portal/apollo-open-api-platform

Register a third-party application, as shown in the following figures.

5
6

4. Activate KMS

You can log on to the KMS console to view and activate KMS.

4.1. Create a Dedicated KMS Instance and a Key

4.2. Create a Dedicated KMS Instance

7

In the KMS console, click Instances in the left-side navigation pane, select a region (such as Beijing), and click Create Instance.

Note:

  1. The KMS instance must be in the same VPC as the server of the application that needs to use the capabilities of configuration encryption and decryption. Otherwise, the capabilities cannot be used.
  2. You do not need to ensure network connectivity between MSE Nacos and the KMS instance.

4.3. Determine KMS Instance Specifications

When you create a dedicated KMS instance, you must determine resource specifications for the instance. Note that only one key is required to use the configuration encryption and decryption capabilities of MSE Nacos. For more information about instance specifications, see Purchase and enable a KMS instance.

4.4. Create a Key

After the KMS instance is created, you also need to create a key. In the KMS console, click Keys in the left-side navigation pane, select a region (such as Beijing), and click Create Key.

4.5. Determine Key Specifications

For a key used for configuration encryption and decryption in MSE Nacos, you must determine two parameters:

  1. Key Type: Select Symmetric Key.
  2. Key Specifications: Select Aliyun_AES_256.

You can set other key parameters based on your requirements. For more information about key management features, see Getting started with keys.

5. Enable Configuration Encryption, Bind the KMS Key to the Apollo Instance, and Create and Use Encrypted Configurations in Apollo

5.1. Connect the KMS Application to the Apollo Configuration Center

    <dependency>
            <groupId>com.ctrip.framework.apollo</groupId>
            <artifactId>apollo-client</artifactId>
            <version>1.7.0</version>
        </dependency>
        <dependency>
            <groupId>com.ctrip.framework.apollo</groupId>
            <artifactId>apollo-openapi</artifactId>
            <version>1.7.0</version>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>alibabacloud-dkms-gcs-sdk</artifactId>
            <version>0.5.2</version>
        </dependency>

5.2. Create the KmSUtils Class and Use Apollo APIs to Query a Configuration Item and Publish It After Encryption

package com.aliyun.demo;
import com.aliyun.dkms.gcs.openapi.models.Config;
import com.aliyun.dkms.gcs.sdk.Client;
import com.aliyun.dkms.gcs.sdk.models.*;
import java.util.Base64;
import java.nio.charset.StandardCharsets;

public class KmsUtils {
    public Client getkmsClient() {
        Client client = null;
        try{
            String caContent="-----BEGIN CERTIFICATE-----\n" +
                    "MIIDuzCCAqOgAwIBAgIJALTKwWAjvbMiMA0GCSqGSIb3DQEBCwUAMHQxCzAJBgNV\n" +
                    "BAYTAkNOMREwDwYDVQQIDAhaaGVKaWFuZzERMA8GA1UEBwwISGFuZ1pob3UxEDAO\n" +
                    "BgNVBAoMB0FsaWJhYmExDzANBgNVBAsMBkFsaXl1bjEcMBoGA1UEAwwTUHJpdmF0\n" +
                    "ZSBLTVMgUm9vdCBDQTAeFw0yMTA3MDgwNjU1MjlaFw00MTA3MDMwNjU1MjlaMHQx\n" +
                    "CzAJBgNVBAYTAkNOMREwDwYDVQQIDAhaaGVKaWFuZzERMA8GA1UEBwwISGFuZ1po\n" +
                    "b3UxEDAOBgNVBAoMB0FsaWJhYmExDzANBgNVBAsMBkFsaXl1bjEcMBoGA1UEAwwT\n" +
                    "UHJpdmF0ZSBLTVMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" +
                    "ggEBAM99IVpxedcGYZVXXX4XZ+bYWw1gVD5Uli9kBrlq3nBT8c0b+4/1W4aQzr+S\n" +
                    "zBEWMrRZaMH3c5rV63qILyy8w4Gm2J0++nIA7uXVhpbliq6lf6p0i3cKpp+JGCbP\n" +
                    "kLvOpONrZ4an/htNE+vpfbsW3WcwcVbmZpQyuGIXIST8iyfTwckZSMkxAPW4rhMa\n" +
                    "QtmQcQiWaJsR0WJoqP7jXcHZobYehnUlzi/ZzdtmnkhTjz0+GvX9/1GBHCyfVEOO\n" +
                    "a0RiT5nEz55xWahZKbj+1nhmInbc7BUqfhz/mbQjtk5lAsJpA8JrbukRhTiAMbj9\n" +
                    "TqUqLe/meEVdjtD6wWsaZoSeoucCAwEAAaNQME4wHQYDVR0OBBYEFAVKzUR5/d6j\n" +
                    "nYM/bHlxURkGhe2EMB8GA1UdIwQYMBaAFAVKzUR5/d6jnYM/bHlxURkGhe2EMAwG\n" +
                    "A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAMCxpkV/KPuKVOBsT4yYkeX1\n" +
                    "Q7IQQoICOAkZOkg7KEej4BJpW2Ml121aFScKxdnRcV2omr48K+GQt/mPNAXgf3k2\n" +
                    "eKQce7xmBwntRplDJFrzdZPBdjel4i62JoWlaTejht2L5ano+x3a3keqF0GoOnn0\n" +
                    "StwpG2xa0S6RmyNFiMugwDBCtSCJAJKr8yAbO+hoe1lQR0M78dy8ENteC/BXuAks\n" +
                    "cktoG0/ryX9EqE9xQ2Do3INDq2PxIuA9yPvZ1eV3xa3bd1u+02feGIrtc9cJ5chf\n" +
                    "vUk5tbgg58NVXrg29yE5eq3j2BErUlAs2LB/Bt/Jhkekvp7qR42btJj+/zQnDSw=\n" +
                    "-----END CERTIFICATE-----\n" +
                    "-----BEGIN CERTIFICATE-----\n" +
                    "MIID4DCCAsigAwIBAgIJAKOtsZIcfRgaMA0GCSqGSIb3DQEBCwUAMHQxCzAJBgNV\n" +
                    "BAYTAkNOMREwDwYDVQQIDAhaaGVKaWFuZzERMA8GA1UEBwwISGFuZ1pob3UxEDAO\n" +
                    "BgNVBAoMB0FsaWJhYmExDzANBgNVBAsMBkFsaXl1bjEcMBoGA1UEAwwTUHJpdmF0\n" +
                    "ZSBLTVMgUm9vdCBDQTAeFw0yMTEyMDgwNzE0MDlaFw00MTEyMDMwNzE0MDlaMIGC\n" +
                    "MQswCQYDVQQGEwJDTjERMA8GA1UECAwIWmhlSmlhbmcxETAPBgNVBAcMCEhhbmda\n" +
                    "aG91MRAwDgYDVQQKDAdBbGliYWJhMQ8wDQYDVQQLDAZBbGl5dW4xKjAoBgNVBAMM\n" +
                    "IVByaXZhdGUgS01TIGNuLXNoYW5naGFpIFNlY29uZCBDQTCCASIwDQYJKoZIhvcN\n" +
                    "AQEBBQADggEPADCCAQoCggEBAL9dlbTTaHtLFNB0Rnda9uYjnuewU99uoK1bwW9n\n" +
                    "NScUdqIlcBTu6xDHFFQSUjC/IkkloHpn1wBg9lUNp9u2YET1/RDQDFYgbinbLv2r\n" +
                    "NhUiu8qcX31K9EXkWPILCsjLHTQIgLmvTgzHTOB2PxWUQmlvgjqaII6cFCTNd0uQ\n" +
                    "fMOBaxg/o5Vjs6dgVQSwC9u6RcXS2VQuWXUo2pk7H3M6zUSXg6RpzZ8HPds+fyIX\n" +
                    "OM5JhLeHaLl0LtwojpSr2yvXifxr1o7uumK+Sp/bAAV2CiN7eC4KX39MWBu6QpaV\n" +
                    "tpKSHuXsH8DizlAidPqQsGVZ8AS1tD2mJXpLCXMeT5TkGy0CAwEAAaNmMGQwHQYD\n" +
                    "VR0OBBYEFJvw48QbrOMQTsrhzsX9exQ1Nb52MB8GA1UdIwQYMBaAFAVKzUR5/d6j\n" +
                    "nYM/bHlxURkGhe2EMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGG\n" +
                    "MA0GCSqGSIb3DQEBCwUAA4IBAQCKz1Y29h/bWNdr20pFg/QJ2c4kF93Rp90CJnqx\n" +
                    "F6TFaabuFbw/42mjB3IB5RtR/+fz5je5WykII/ST4xQdKCU3reU6zZ3jU9erhHVP\n" +
                    "8G1om0hfiiDnYJ3E/03JAzXWWlrztR9fE5aVEAxXDoJQs2gJZJLIQOKjesDh6+gr\n" +
                    "FwLb4ltDYHMNlN1HCj31Z8NxWUtnIH7Xv1c93FTCFoeOc9fssNDgsy5FFXy0XIkm\n" +
                    "1xrT6gQcxRKoDCC4LwEmLwV3S1OfrNXhgJzx1R65pahAzjJR0vgWU8NbkmY8ZZS8\n" +
                    "i6LVVFDar9z0K/8UN1n+nl6saJSUuVFdWzHBRX4wYuUxQI+P\n" +
                    "-----END CERTIFICATE-----\n";
            // KMS client key certification.
            String protocol = "https";
            String endpoint = "kst-sXXXXp.cryptoservice.kms.aliyuncs.com"; // The connected KMS endpoint.
            String clientKeyContent="{\n" +
                    "  \"KeyId\": \"KAAP.4b922417-XXXXX-b73e-cc841101bda0\",\n" +
                    "  \"PrivateKeyData\": \"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\"\n" +
                    "}";
            String clientKeyPass = "3a32bced4XXXXXXe47d050a76";
            client = new Client(new Config().setProtocol(protocol).setEndpoint(endpoint).setCa(caContent).setClientKeyContent(clientKeyContent).setPassword(clientKeyPass));
            //System.out.println("print kms client--------------");
            if(client !=null){
                System.out.println(client.toString());
                //System.out.println("--------------kms client init success-----");
                //System.out.println("\n");
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        return client;
    }

    public String Enc(Client client,String data,String keyId){
        String cipherblobtext=null;
        try {
            String cipherKeyId = keyId;
            //Data to be encrypted. [The data here is processed according to the actual business situation, and the following examples are for reference only]
            byte[] plaintext = data.getBytes(StandardCharsets.UTF_8);
            AdvanceEncryptRequest advanceEncryptRequest = new AdvanceEncryptRequest();
            advanceEncryptRequest.setKeyId(cipherKeyId);
            advanceEncryptRequest.setPlaintext(plaintext);
            //encrypt your plaintext data
            AdvanceEncryptResponse encryptResponse = client.advanceEncrypt(advanceEncryptRequest);
            cipherblobtext= Base64.getEncoder().encodeToString(encryptResponse.getCiphertextBlob());
           // System.out.println("cipherblobtext : "+cipherblobtext);
        }catch (Exception e){e.printStackTrace();}
        return cipherblobtext;
    }

    public String Dec(Client client,String cipherblobtext){
        String plaintext=null;
        try {
            AdvanceDecryptRequest decryptRequest = new AdvanceDecryptRequest();
            byte[] cipherblob = Base64.getDecoder().decode(cipherblobtext);
            decryptRequest.setCiphertextBlob(cipherblob);
            AdvanceDecryptResponse decryptResponse = client.advanceDecrypt(decryptRequest);
            plaintext=new String(decryptResponse.getPlaintext());
        }catch (Exception e){e.printStackTrace();}
        return plaintext;

    }

}

5.3. Use Apollo APIs to Add a Configuration Item and Obtain It for Printing

package com.aliyun.demo;
import com.aliyun.dkms.gcs.sdk.Client;
import com.ctrip.framework.apollo.openapi.client.ApolloOpenApiClient;
import com.ctrip.framework.apollo.openapi.dto.NamespaceReleaseDTO;
import com.ctrip.framework.apollo.openapi.dto.NamespaceReleaseDTO;
import java.util.Date;

public class ApolloTest {

    public static void main(String[] args) {
        KmsUtils kmsUtils=new KmsUtils();
        Client kmsClient=kmsUtils.getkmsClient();
        String keyId="key-bjj65669e7ddfXXXX2l";
        String portalUrl = "http://XXXXX/"; // The address of the Apollo portal.
        String token = "2cb13b3581eb7XXXXa02eb2c3"; // The requested token.
        ApolloOpenApiClient client = ApolloOpenApiClient.newBuilder().withPortalUrl(portalUrl).withToken(token).build();
        System.out.println("token : "+client.getToken());
        System.out.println("url : "+client.getPortalUrl());
        System.out.println("apps : "+client.getAllApps());
        OpenItemDTO opt=client.getItem("test","dev","default","application","user");
        System.out.println("item old : "+opt+"\n");
        //Create Apollo Item
        opt.setKey("test-user");
        String value=kmsUtils.Enc(kmsClient,"this is your apollo item value",keyId);
        //System.out.println("value : \n"+value);
        opt.setValue(value);
        opt.setComment("xxx");
        opt.setDataChangeCreatedTime(new Date());
        client.createOrUpdateItem("test","dev","default","application",opt);
        //Get Apollo Item
        OpenItemDTO openItemDTO=client.getItem("test","dev","default","application","test-user");
      System.out.println("print apollo item key :  "+openItemDTO.getKey());
        System.out.println("print decrypted value : "+kmsUtils.Dec(kmsClient,openItemDTO.getValue()));
    // release Apollo Namespace
        NamespaceReleaseDTO nsrdto=new NamespaceReleaseDTO();
        nsrdto.setReleaseTitle("application title");
        nsrdto.setReleaseComment("release comment xxxx");
        nsrdto.setReleasedBy("apollo");
        client.publishNamespace("test","dev","default","application",nsrdto);
  }

}

6. Running Results in Apollo

8
9

6.1. View the Running Results on the Apollo Admin Platform

10
11
12


Disclaimer: The views expressed herein are for reference only and don't necessarily represent the official views of Alibaba Cloud.

0 1 0
Share on

Alibaba Cloud Community

1,035 posts | 254 followers

You may also like

Comments