# Config Center Service

## What is Config Center

A configuration center is a centralized component used to manage environment-specific parameters for a microservice application. 
These parameters may include:  
- Database connection strings 
- Server addresses 
- API keys 
- Other settings that vary between environments

### Benefits of Using a Configuration Center
Using a configuration center simplifies managing and maintaining multiple environments, like development, staging, and production. Instead of hardcoding environment-specific settings into the application code, these settings can be stored in the configuration center and accessed at runtime.

This approach has several advantages:

1. **Simplify Updates:** It allows for easy configuration changes without having to modify and redeploy application code. 

2. **Reduce Risk:** It can help prevent errors caused by environment-specific settings being inadvertently included in code repositories or deployment packages. 

3. **Enhance Security:** It can improve security by allowing sensitive parameters to be stored separately from application code and only accessed by authorized users.


## How to Use Config Center

- Configuration rules
  - The key of the configuration center data is separated by **'/'**, where each level has different meanings. The value is the configuration data. If it is the current effective environment, the environment name is local.


![configcenter_rule](./image/configcenter/configcenter_rule.png)  

- View configuration  
  - Three modes: **Table**、**Tree** and **JSON** 
  
![configcenter_view](./image/configcenter/configcenter_view.png)  

- Add configuration 
  - Add key：**value**

![configcenter_create](./image/configcenter/configcenter_create.png)  

- Delete configuration
  - Two modes of deletion

![configcenter_delete](./image/configcenter/configcenter_delete.png)  

  - Batch deletion
  
![configcenter_batch_delete](./image/configcenter/configcenter_batch_delete.png)  

### Service Integration

- Template integration
  - The integration method is simple and easy to operate, convenient and fast.
- SDK integration
  - You can add the SDK provided by insureMO with less dependence.
- API Integration
  - You need to get the processing configuration yourself. 

### Data Storage

For private installation, it's important to understand that config-center is powered by eted in the backend as separate middleware.
- About etcd<br>
Etcd is a distributed key-value store that can be used to store and retrieve configuration data in a reliable, scalable, and highly available manner. In distributed systems, it is often used for:
    - Service discovery 
    - Configuration management
    - Coordination in distributed systems

Using etcd for configuration management allows to store configuration data as key-value pairs, where each key represents a configuration parameter and each value represents its corresponding value. 

By organizing configuration data in this way, users can easily manage different configurations for different environments by creating separate keys for each environment.


### Usage Scenario

- Unified management of service configuration
- The service calls and reads configuration

## Page

- [Config center](https://portal.insuremo.com/#/home/utility-and-admin/configcenter)

## API

> The latest API version is V2, with the base path `/config/v2`. The V1 APIs (`/config/export`, `/config/import`, `/config/configs`) are deprecated.  
> V2 APIs require MO user authentication (via gateway Bearer token).  
> Gateway URL format: `{{insuremo_gw_url}}/mo-fo/v1/config/v2/{endpoint}`

### Get Configuration (Service Invocation)

- GET request：  
  `{{insuremo_gw_url}}/mo-fo/v1/config/v2/configs`
- Query Params：

  | Parameter | Required | Description |
  |-----------|----------|-------------|
  | `profile` | Yes | Tenant code, e.g. `foundation` |
  | `environment` | No | Environment name, default is `local` |
  | `application` | No | Application name, e.g. `urp-service` |
  | `key` | No | Specific key name |
  | `mode` | No | Set to `mix` to merge public application configs with the specified application configs |

- Headers：  
  `Authorization: Bearer xxxxxxxxxxxxxxxxxx`

- Response: Returns decrypted plaintext values. Sensitive configs are automatically decrypted before returning.

- Response Body：

  ```json
  {
    "code": "i_common_success",
    "message": "request success",
    "trace_id": "",
    "env_name": "test_env",
    "date": "2026-07-29T03:46:38.224Z",
    "data": {
      "env": "local",
      "profile": "tenant-a",
      "application": "my-app",
      "label": "",
      "key": "",
      "data": {
        "db.host": "localhost",
        "db.port": "3306"
      }
    }
  }
  ```

  | Field | Type | Description |
  |-------|------|-------------|
  | `code` | string | Response code, e.g. `i_common_success` |
  | `message` | string | Response message |
  | `trace_id` | string | Trace ID for request tracking |
  | `env_name` | string | Environment name |
  | `date` | string | Response timestamp (ISO 8601) |
  | `data.env` | string | Environment |
  | `data.profile` | string | Tenant code |
  | `data.application` | string | Application name |
  | `data.label` | string | Label |
  | `data.key` | string | Key filter |
  | `data.data` | map[string]string | Key-value pairs of configuration data (decrypted plaintext) |

### Export Configuration

- GET request：  
  `{{insuremo_gw_url}}/mo-fo/v1/config/v2/export`
- Query Params：

  | Parameter | Required | Description |
  |-----------|----------|-------------|
  | `profile` | Yes | Tenant code, e.g. `foundation` |
  | `environment` | No | Environment name, e.g. `dev`, `tst`. Default is `local` |
  | `application` | No | Application name, e.g. `urp-service` |
  | `key` | No | Specific key name to export |
  | `included_prefix` | No | Only export keys with this prefix |
  | `excluded_prefix` | No | Exclude keys with this prefix |
  | `ignore_meta_data` | No | Ignore meta data in export |

- Headers：  
  `Authorization: Bearer xxxxxxxxxxxxxxxxxx`

- Response: Returns encrypted/masked values. Sensitive configs are exported as `*mo_encrypted*` ciphertext.

- Response Body：

  ```json
  {
    "code": "i_common_success",
    "message": "request success",
    "trace_id": "",
    "env_name": "test_env",
    "date": "2026-07-29T03:46:38.224Z",
    "data": {
      "env": "local",
      "profile": "tenant-a",
      "application": "my-app",
      "label": "",
      "key": "",
      "data": {
        "db.host": "ENC(xxxx)",
        "db.port": "3306"
      }
    }
  }
  ```

  | Field | Type | Description |
  |-------|------|-------------|
  | `code` | string | Response code, e.g. `i_common_success` |
  | `message` | string | Response message |
  | `trace_id` | string | Trace ID for request tracking |
  | `env_name` | string | Environment name |
  | `date` | string | Response timestamp (ISO 8601) |
  | `data.env` | string | Environment |
  | `data.profile` | string | Tenant code |
  | `data.application` | string | Application name |
  | `data.label` | string | Label |
  | `data.key` | string | Key filter |
  | `data.data` | map[string]string | Key-value pairs of configuration data (sensitive values encrypted as `ENC(...)`) |

### Import Configuration

- POST request：  
  `{{insuremo_gw_url}}/mo-fo/v1/config/v2/import`
- Query Params：

  | Parameter | Required | Description |
  |-----------|----------|-------------|
  | `is_hard` | No | If `true`, data containing `mo_deleted` will not be deleted |

- Request Body：

  ```json
  {
    "env": "local",
    "profile": "foundation",
    "application": "urp-service",
    "label": "",
    "key": "",
    "included_prefix": "",
    "excluded_prefix": "",
    "data": {
      "db.type": "mysql",
      "db.host": "172.25.14.34"
    }
  }
  ```

  | Field | Type | Description |
  |-------|------|-------------|
  | `env` | string | Environment name |
  | `profile` | string | Tenant code |
  | `application` | string | Application name |
  | `label` | string | Label |
  | `key` | string | Key name |
  | `included_prefix` | string | Only import keys with this prefix |
  | `excluded_prefix` | string | Exclude keys with this prefix |
  | `data` | map[string]string | Key-value pairs of configuration data |

- Headers：  
  `Authorization: Bearer xxxxxxxxxxxxxxxxxx`

- Note: Sensitive keys (matching `pwd/password/secret/token/credential/key`) are automatically AES-encrypted on write.

- Response Body：

  ```json
  {
    "code": "i_common_success",
    "message": "request success",
    "trace_id": "",
    "env_name": "test_env",
    "date": "2026-07-29T03:46:38.224Z",
    "data": {
      "revision": "12345",
      "version": "v1.0.0",
      "count": {
        "put": 2,
        "delete": 0,
        "get": 0
      },
      "operator": "admin",
      "tenant_code": "tenant-a",
      "query_params": "version=v1.0.0",
      "modify_time": "2026-07-29T10:00:00Z",
      "trace_id": "abc123"
    }
  }
  ```

  | Field | Type | Description |
  |-------|------|-------------|
  | `code` | string | Response code, e.g. `i_common_success` |
  | `message` | string | Response message |
  | `trace_id` | string | Trace ID for request tracking |
  | `env_name` | string | Environment name |
  | `date` | string | Response timestamp (ISO 8601) |
  | `data.revision` | string | Revision number of the import |
  | `data.version` | string | Version of the import |
  | `data.count.put` | number | Number of keys written |
  | `data.count.delete` | number | Number of keys deleted |
  | `data.count.get` | number | Number of keys read |
  | `data.operator` | string | Operator who performed the import |
  | `data.tenant_code` | string | Tenant code |
  | `data.query_params` | string | Query parameters used |
  | `data.modify_time` | string | Last modification time (ISO 8601) |
  | `data.trace_id` | string | Trace ID for this operation |


## Secret Manager Integration

Besides the built-in AES encryption for sensitive keys, Config Center can reference secrets that live in an **external secret manager**. Instead of storing the real secret value, you store a tagged reference. The real value is resolved on the fly when the configuration is read (service invocation / decrypted plaintext responses) and is never persisted inside Config Center.

Two secret managers are supported:

- **AWS Secrets Manager**
- **HashiCorp Vault**

You reference an external secret by writing a specially tagged value for the config key. The tag prefix tells Config Center which secret manager to resolve against.

| Secret Manager | Tag prefix | Reference format |
|----------------|------------|------------------|
| AWS Secrets Manager | `*mo_aws_secret_manager*` | `*mo_aws_secret_manager*<secretName>[:key]` |
| HashiCorp Vault | `*mo_vault_secret*` | `*mo_vault_secret*<path>[:key]` |

### AWS Secrets Manager

- **Reference format:** `*mo_aws_secret_manager*<secretName>[:key]`
  - `secretName`: the AWS Secrets Manager secret name or ARN
  - `key` (optional): when the secret is a JSON object, only this field is extracted
- **Resolution behavior** (secret version stage `AWSCURRENT`):
  - JSON secret **with** `:key` → returns that field's value
  - JSON secret **without** `:key` → returns the whole JSON string
  - Non-JSON secret (e.g. a PEM certificate) → returns the raw value as-is

- **Example**

  ```json
  {
    "db.password": "*mo_aws_secret_manager*prod/db/credential:password",
    "tls.cert": "*mo_aws_secret_manager*prod/tls/server-cert"
  }
  ```

- **Configuration**

  AWS Secrets Manager uses the same AWS credentials as the AWS storage backends. Credentials are resolved in the following order:

  1. **Static access key / secret key** — set `AWSAccessKeyID` + `AWSSecretKey` (+ `AWSRegion`).
  2. **Web Identity + STS AssumeRole** (EKS / IRSA) — set `AWSRoleARN`, `AWSDynamodbRoleARN`, and `AWSWebIdentityToken`.
  3. **Default EC2 / EKS role** — no explicit credentials; resolved from the default AWS credential chain.

  | Config | Description |
  |--------|-------------|
  | `AWSAccessKeyID` | AWS access key ID (static credentials) |
  | `AWSSecretKey` | AWS secret access key (static credentials) |
  | `AWSRegion` | AWS region |
  | `AWSRoleARN` | Role ARN assumed via Web Identity token |
  | `AWSDynamodbRoleARN` | Second role ARN assumed after the Web Identity role |
  | `AWSWebIdentityToken` | Path to the Web Identity token file |

### HashiCorp Vault

- **Reference format:** `*mo_vault_secret*<path>[:key]`
  - `path`: the KV v2 secret path, excluding the mount, e.g. `app/prod/db`
  - `key` (optional): the field to extract from the secret data
- **Authentication:** Vault **AppRole** (`role_id` + `secret_id`). The client token is cached and automatically renewed shortly before it expires.
- **Resolution behavior** (reads `GET /v1/<mount>/data/<path>`):
  - `:key` specified → returns that field's value
  - no `:key`, single field → returns that field directly (e.g. a certificate)
  - no `:key`, multiple fields → returns the whole data map as a JSON string

- **Example**

  ```json
  {
    "db.password": "*mo_vault_secret*app/prod/db:password",
    "tls.key": "*mo_vault_secret*app/prod/tls-key"
  }
  ```

- **Configuration** (environment variables)

  | Env | Description | Default |
  |-----|-------------|---------|
  | `VAULT_ADDR` | Vault server address, e.g. `https://vault.example.com` | - |
  | `VAULT_ROLE_ID` | AppRole `role_id` | - |
  | `VAULT_SECRET_ID` | AppRole `secret_id` | - |
  | `VAULT_MOUNT` | KV v2 secret engine mount point | `secret` |
  | `VAULT_NAMESPACE` | Vault namespace (Vault Enterprise only) | - |

  `VAULT_ADDR`, `VAULT_ROLE_ID`, and `VAULT_SECRET_ID` are required to enable Vault integration.
