Skip to content

Commit 2629df1

Browse files
Merge pull request #6 from nwn2dev/feature/ssl
Final touches to TLS security
2 parents 3e76ae0 + 9354471 commit 2629df1

File tree

8 files changed

+94
-63
lines changed

8 files changed

+94
-63
lines changed

.github/workflows/build.yml

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,36 @@
1-
name: NWNX4-plugins-xp_rpc
1+
name: nwnx4-plugin-rpc
22
on: [push, pull_request]
33

44
jobs:
55
build:
66
name: Build NWNX4 plugin xp_rpc
77
runs-on: windows-latest # Change the operating system to Windows
8+
defaults:
9+
run:
10+
shell: powershell
811

912
steps:
10-
- uses: actions/checkout@v2
13+
- uses: actions/checkout@v3
1114
with:
1215
fetch-depth: 0
1316
submodules: recursive
1417

15-
- name: Install MSYS2
16-
run: |
17-
choco install msys2 --params "/NoUpdate"
18-
19-
- name: Refresh MSYS2 installation
20-
run: |
21-
RefreshEnv
22-
C:\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -Syu"
23-
24-
- name: Install MinGW-w64 32-bit
25-
run: |
26-
C:\msys64\usr\bin\bash.exe -lc "pacman --noconfirm -S mingw-w64-i686-toolchain"
18+
- name: Setup MSYS2/MinGW-w64 32-bit
19+
uses: msys2/setup-msys2@v2
20+
with:
21+
msystem: UCRT64
22+
update: true
23+
install: mingw-w64-i686-gcc
2724

28-
- name: Set MinGW-w64 environment variables
29-
run: |
30-
";C:\msys64\mingw32\bin" | Out-File -FilePath $env:GITHUB_PATH -Append
25+
- name: Add MinGW-w64 to path
26+
run: echo "${{ runner.temp }}/msys64/mingw32/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
3127

3228
- name: Setup Go
33-
uses: actions/setup-go@v2
29+
uses: actions/setup-go@v4
3430
with:
3531
go-version: 1.17
3632

3733
- name: Build Win32 x86 DLL for NWNX4
38-
shell: powershell
3934
env:
4035
GOOS: windows
4136
GOARCH: 386
@@ -44,7 +39,6 @@ jobs:
4439
run: go build -ldflags '-s -w -linkmode external -extldflags -static-libgcc -extldflags -static-libstdc++' -o ../dist/xp_rpc.dll -buildmode=c-shared
4540

4641
- name: Copy all necessary files into distribution
47-
shell: powershell
4842
run: |
4943
Copy-Item -Recurse -Path .\include -Destination .\dist
5044
Copy-Item -Recurse -Path .\proto -Destination .\dist

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ With a created external application, configure your xp_rpc settings for the clie
5454

5555
```yaml
5656
auth:
57-
certPath: path/to/cert
57+
pfxFilePath: path/to/pfx
58+
pfxPassword: password
5859
log:
5960
logLevel: info
6061
perClient:

plugin/go.mod

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@ go 1.18
44

55
require (
66
github.com/sirupsen/logrus v1.9.0
7+
golang.org/x/crypto v0.18.0
78
google.golang.org/grpc v1.54.0
9+
google.golang.org/protobuf v1.28.1
810
gopkg.in/yaml.v3 v3.0.1
911
)
1012

1113
require (
1214
github.com/golang/protobuf v1.5.2 // indirect
13-
golang.org/x/net v0.8.0 // indirect
14-
golang.org/x/sys v0.6.0 // indirect
15-
golang.org/x/text v0.8.0 // indirect
15+
golang.org/x/net v0.10.0 // indirect
16+
golang.org/x/sys v0.16.0 // indirect
17+
golang.org/x/text v0.14.0 // indirect
1618
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
17-
google.golang.org/protobuf v1.28.1 // indirect
1819
)

plugin/go.sum

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs
1313
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
1414
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
1515
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
16-
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
17-
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
16+
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
17+
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
18+
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
19+
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
1820
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
19-
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
20-
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
21-
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
22-
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
21+
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
22+
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
23+
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
24+
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
2325
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
2426
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
2527
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=

plugin/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import (
3333
const pluginID string = "RPC" // Plugin ID used for identification in the list
3434
const pluginName string = "NWNX RPC Plugin" // Plugin name passed to hook
3535
const pluginDescription string = "A better way to integrate services with NWN2"
36-
const pluginVersion string = "0.5.1" // Plugin version passed to hook
36+
const pluginVersion string = "0.5.2" // Plugin version passed to hook
3737
const pluginContact string = "(c) 2021-2024 by ihatemundays ([email protected])"
3838

3939
const logFilename string = "xp_rpc.log"

plugin/rpc_client.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@ type rpcClient struct {
1717
scorcoServiceClient pb.SCORCOServiceClient
1818
}
1919

20+
func newRpcClient(name, url string) *rpcClient {
21+
return &rpcClient{
22+
isValid: false,
23+
name: name,
24+
url: url,
25+
exServiceClient: nil,
26+
nwnxServiceClient: nil,
27+
scorcoServiceClient: nil,
28+
}
29+
}
30+
2031
func (c rpcClient) buildGeneric(request *pb.ExBuildGenericRequest, timeout time.Duration) (*pb.ExBuildGenericResponse, error) {
2132
ctx, cancel := context.WithTimeout(context.Background(), timeout)
2233
defer cancel()

plugin/rpc_config.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import "time"
44

55
type rpcConfig struct {
66
Auth struct {
7-
CertPath *string `yaml:"certPath"`
7+
PfxFilePath *string `yaml:"pfxFilePath"`
8+
PfxPassword *string `yaml:"pfxPassword"`
89
} `yaml:"auth"`
910
Log struct {
1011
LogLevel string `yaml:"logLevel" default:"info"`

plugin/rpc_plugin.go

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package main
22

33
import (
4+
"crypto/tls"
5+
"crypto/x509"
46
log "github.com/sirupsen/logrus"
7+
"golang.org/x/crypto/pkcs12"
58
"google.golang.org/grpc/credentials"
69
"google.golang.org/grpc/credentials/insecure"
710
pb "nwnx4.org/nwn2dev/xp_rpc/proto"
11+
"os"
812
"strings"
913
"time"
1014
)
@@ -33,7 +37,7 @@ const rpcEndBuildGeneric int32 = 2
3337

3438
type rpcPlugin struct {
3539
config rpcConfig
36-
certPath *string
40+
creds credentials.TransportCredentials
3741
clients map[string]*rpcClient
3842
globalExBuildGenericRequest *pb.ExBuildGenericRequest
3943
globalExBuildGenericResponse *pb.ExBuildGenericResponse
@@ -43,7 +47,7 @@ type rpcPlugin struct {
4347
func newRpcPlugin() *rpcPlugin {
4448
return &rpcPlugin{
4549
config: rpcConfig{},
46-
certPath: nil,
50+
creds: insecure.NewCredentials(),
4751
clients: make(map[string]*rpcClient),
4852
globalExBuildGenericRequest: newExBuildGenericRequest(),
4953
globalExBuildGenericResponse: newExBuildGenericResponse(),
@@ -67,6 +71,49 @@ func newExBuildGenericResponse() *pb.ExBuildGenericResponse {
6771
func (p *rpcPlugin) init() {
6872
log.Info("Initializing RPC plugin")
6973

74+
// Add a certificate
75+
getCredentials := func() {
76+
if p.config.Auth.PfxFilePath == nil && p.config.Auth.PfxPassword == nil {
77+
log.Info("Using insecure auth. settings")
78+
79+
return
80+
}
81+
82+
pfxFilePath, pfxPassword := *p.config.Auth.PfxFilePath, ""
83+
84+
if p.config.Auth.PfxPassword != nil {
85+
pfxPassword = *p.config.Auth.PfxPassword
86+
}
87+
88+
// Load the PFX file
89+
pfxData, err := os.ReadFile(pfxFilePath)
90+
if err != nil {
91+
log.Fatalf("Error reading PFX file: %v", err)
92+
}
93+
94+
// Parse the PFX data to get the certificate
95+
_, cert, err := pkcs12.Decode(pfxData, pfxPassword)
96+
if err != nil {
97+
log.Fatalf("Error decoding PFX file: %v", err)
98+
}
99+
100+
// Create a new certificate pool and add the certificate
101+
caCertPool := x509.NewCertPool()
102+
caCertPool.AddCert(cert)
103+
104+
// Create a TLS configuration using the parsed certificate
105+
tlsConfig := &tls.Config{
106+
RootCAs: caCertPool,
107+
InsecureSkipVerify: true,
108+
}
109+
110+
// Create a credentials object from the TLS configuration
111+
p.creds = credentials.NewTLS(tlsConfig)
112+
113+
log.Info("Using secure auth. settings")
114+
}
115+
getCredentials()
116+
70117
// Set the log level based on what was passed if it matches a level
71118
for _, logLevel := range log.AllLevels {
72119
if strings.EqualFold(logLevel.String(), p.config.Log.LogLevel) {
@@ -92,38 +139,12 @@ func (p *rpcPlugin) addRpcClient(name, url string) {
92139
// Load the certificate
93140
var conn *grpc.ClientConn
94141
var err error
95-
if p.certPath != nil {
96-
creds, err := credentials.NewClientTLSFromFile(*p.certPath, "")
97-
if err != nil {
98-
log.Errorf("Unable to load certificate: %v", err)
99-
p.clients[name] = &rpcClient{
100-
isValid: false,
101-
name: name,
102-
url: url,
103-
exServiceClient: nil,
104-
nwnxServiceClient: nil,
105-
scorcoServiceClient: nil,
106-
}
107-
return
108-
}
109-
110-
conn, err = grpc.Dial(url, grpc.WithTransportCredentials(creds))
111-
} else {
112-
conn, err = grpc.Dial(url, grpc.WithTransportCredentials(insecure.NewCredentials()))
113-
}
142+
conn, err = grpc.Dial(url, grpc.WithTransportCredentials(p.creds))
114143

115144
// Dial with the loaded certificate
116145
if err != nil {
117146
log.Errorf("Unable to attach client: %s@%s", name, url)
118-
119-
p.clients[name] = &rpcClient{
120-
isValid: false,
121-
name: name,
122-
url: url,
123-
exServiceClient: nil,
124-
nwnxServiceClient: nil,
125-
scorcoServiceClient: nil,
126-
}
147+
p.clients[name] = newRpcClient(name, url)
127148

128149
return
129150
}

0 commit comments

Comments
 (0)