Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
- './wrappers/static'
- './wrappers/tencentcloudkms'
- './wrappers/transit'
- './wrappers/nhncloudskm'
go: ["1.22"]
platform: [ubuntu-latest] # can not run in macOS and Windows
runs-on: ${{ matrix.platform }}
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ test:
cd wrappers/static && go test ./... $(TESTARGS)
cd wrappers/tencentcloudkms && go test ./... $(TESTARGS)
cd wrappers/transit && go test ./... $(TESTARGS)
cd wrappers/nhncloudskm && go test ./... $(TESTARGS)

.PHONY: proto
proto:
Expand Down Expand Up @@ -46,6 +47,7 @@ tidy-all:
cd wrappers/tencentcloudkms && go mod tidy
cd wrappers/static && go mod tidy
cd wrappers/transit && go mod tidy
cd wrappers/nhncloudskm && go mod tidy
go mod tidy

.PHONY: generate-all
Expand All @@ -64,6 +66,7 @@ generate-all:
cd wrappers/static && GOARCH= GOOS= go generate ./...
cd wrappers/tencentcloudkms && GOARCH= GOOS= go generate ./...
cd wrappers/transit && GOARCH= GOOS= go generate ./...
cd wrappers/nhncloudskm && GOARCH= GOOS= go generate ./...
GOARCH= GOOS= go generate ./...

.PHONY: fmt
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ as they may have been used for past encryption operations.
* * Huawei Cloud KMS (uses envelopes)
* * OCI KMS (uses envelopes)
* * Tencent Cloud KMS (uses envelopes)
* * Vault Transit mount
* * NHN Cloud SKM (uses envelopes)
* Vault Transit mount
* Supports generic integrations
* * PKCS11
* * KMIP
Expand Down
1 change: 1 addition & 0 deletions const.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const (
WrapperTypeShamir WrapperType = "shamir"
WrapperTypeTencentCloudKms WrapperType = "tencentcloudkms"
WrapperTypeTransit WrapperType = "transit"
WrapperTypeNHNCloudSkm WrapperType = "nhncloudskm"
WrapperTypeStatic WrapperType = "static"
WrapperTypeTest WrapperType = "test-auto"
)
Expand Down
151 changes: 151 additions & 0 deletions wrappers/nhncloudskm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# NHN Cloud SKM wrapper

Provides integration with NHN Cloud Secure Key Manager (SKM) for encryption and decryption operations using envelope encryption.

## Settings

| Environment variable | Required | Default | Description |
| --------------------------------------- | -------- | -------------------------------------------- | ---------------------------------------------- |
| NHN_CLOUD_SKM_KEY_ID | yes | | Symmetric key ID for encryption operations |
| NHN_CLOUD_SKM_APP_KEY | yes | | NHN Cloud project app key |
| NHN_CLOUD_SKM_USER_ACCESS_KEY_ID | yes | | NHN Cloud user access key ID |
| NHN_CLOUD_SKM_USER_SECRET_ACCESS_KEY | yes | | NHN Cloud user secret access key |
| NHN_CLOUD_SKM_ENDPOINT | no | https://api-keymanager.nhncloudservice.com | NHN Cloud SKM API endpoint |
| NHN_CLOUD_SKM_MAC_ADDRESS | no | | Client MAC address for additional security |

## Features

### Envelope Encryption
The NHN Cloud SKM wrapper uses envelope encryption to handle data of any size:

1. **Data Encryption Key (DEK)**: A 32-byte AES-256 key is generated for each encryption operation
2. **Data Encryption**: The actual data is encrypted using AES-GCM with the DEK
3. **Key Encryption**: The DEK is encrypted using NHN Cloud SKM
4. **Storage**: Both encrypted data and encrypted DEK are stored together

### Key Rotation Support
- **Automatic Tracking**: Tracks key versions returned by NHN Cloud SKM API
- **Version Management**: Stores key version information for proper decryption
- **Seamless Rotation**: Supports key rotation without data migration

### Supported Mechanisms
- **Direct Encryption** (Legacy): For backward compatibility with existing encrypted data
- **Envelope Encryption** (Default): For new encryption operations, supports unlimited data size

## Configuration Examples

### Using Environment Variables
```bash
export NHN_CLOUD_SKM_APP_KEY="your-app-key"
export NHN_CLOUD_SKM_KEY_ID="your-key-id"
export NHN_CLOUD_SKM_USER_ACCESS_KEY_ID="your-access-key-id"
export NHN_CLOUD_SKM_USER_SECRET_ACCESS_KEY="your-secret-access-key"
export NHN_CLOUD_SKM_MAC_ADDRESS="your-mac-address" # Optional
```

### Using Configuration Map
```go
wrapper := nhncloudskm.NewWrapper()
_, err := wrapper.SetConfig(ctx, wrapping.WithConfigMap(map[string]string{
"app_key": "your-app-key",
"key_id": "your-key-id",
"user_access_key_id": "your-access-key-id",
"user_secret_access_key": "your-secret-access-key",
"endpoint": "https://api-keymanager.nhncloudservice.com",
"mac_address": "your-mac-address", // Optional
}))
```

### Using Wrapper Options
```go
wrapper := nhncloudskm.NewWrapper()
_, err := wrapper.SetConfig(ctx,
wrapping.WithKeyId("your-key-id"),
nhncloudskm.WithAppKey("your-app-key"),
nhncloudskm.WithUserAccessKeyID("your-access-key-id"),
nhncloudskm.WithUserSecretAccessKey("your-secret-access-key"),
nhncloudskm.WithEndpoint("https://api-keymanager.nhncloudservice.com"),
nhncloudskm.WithMACAddress("your-mac-address"), // Optional
)
```

## NHN Cloud SKM Requirements

- Valid NHN Cloud project with Secure Key Manager (SKM) service enabled
- Symmetric key created in NHN Cloud SKM console
- User account with SKM access permissions
- Authentication method configured (one or more):
- IPv4 address authentication
- MAC address authentication
- Client certificate authentication

## Security Considerations

### Authentication
- Uses NHN Cloud user credentials for API authentication
- Supports optional MAC address filtering for enhanced security

### Encryption Details
- **Data Encryption**: AES-256-GCM for actual data
- **Key Protection**: NHN Cloud SKM symmetric key encryption
- **Integrity**: Built-in integrity verification through AES-GCM

### Best Practices
- Rotate NHN Cloud user credentials regularly
- Use different keys for different environments (dev/staging/production)
- Configure appropriate authentication methods (IPv4/MAC/Certificate)
- Monitor key usage and access through NHN Cloud SKM console
- Use approval workflows for production key management

## Compatibility

### OpenBao Integration
This wrapper is designed for use with OpenBao auto-unseal functionality:

```hcl
seal "nhncloudskm" {
app_key = "your-app-key"
key_id = "your-key-id"
user_access_key_id = "your-access-key-id"
user_secret_access_key = "your-secret-access-key"
endpoint = "https://api-keymanager.nhncloudservice.com"
mac_address = "your-mac-address" # Optional
}
```

### Backward Compatibility
- Supports decryption of data encrypted with direct encryption method
- New encryptions use envelope encryption by default
- Seamless migration path for existing encrypted data

## Error Handling

Common error scenarios and solutions:

| Error | Cause | Solution |
|-------|-------|----------|
| `app key is required` | Missing app key configuration | Set `NHN_CLOUD_SKM_APP_KEY` environment variable |
| `key ID is required` | Missing key ID configuration | Set `NHN_CLOUD_SKM_KEY_ID` environment variable |
| `user access key ID is required` | Missing access key | Set `NHN_CLOUD_SKM_USER_ACCESS_KEY_ID` environment variable |
| `user secret access key is required` | Missing secret key | Set `NHN_CLOUD_SKM_USER_SECRET_ACCESS_KEY` environment variable |
| `encryption API failed: invalid app key` | Invalid app key | Verify app key in NHN Cloud console |
| `key decryption failed` | Key access denied or invalid key ID | Check key permissions and key ID |

## Testing

### Unit Tests
```bash
go test ./...
```

### Acceptance Tests
Requires valid NHN Cloud SKM credentials:
```bash
export NHNCLOUD_SKM_ACCEPTANCE_TESTS=1
export NHN_CLOUD_SKM_APP_KEY="your-app-key"
export NHN_CLOUD_SKM_KEY_ID="your-key-id"
export NHN_CLOUD_SKM_USER_ACCESS_KEY_ID="your-access-key-id"
export NHN_CLOUD_SKM_USER_SECRET_ACCESS_KEY="your-secret-access-key"

go test ./... -v
```
28 changes: 28 additions & 0 deletions wrappers/nhncloudskm/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module github.com/openbao/go-kms-wrapping/wrappers/nhncloudskm/v2

go 1.24.0

toolchain go1.24.6

replace github.com/openbao/go-kms-wrapping/v2 => ../../

require (
github.com/openbao/go-kms-wrapping/v2 v2.5.0
github.com/stretchr/testify v1.11.1
)

require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 // indirect
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
github.com/hashicorp/go-sockaddr v1.0.7 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
google.golang.org/protobuf v1.36.9 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

retract [v2.0.0, v2.0.2]
36 changes: 36 additions & 0 deletions wrappers/nhncloudskm/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM=
github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0=
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts=
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4=
github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw=
github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw=
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading
Loading